1

Wir haben eine NestedScrollView, die zwei verschiedene RecyclerView beide mit vertikalen Scroll arbeiten enthält. Das Scroll-Layout liegt innerhalb SwipeRefreshLayout.RecyclerView notifyDataSetChanged() friert UI ohne ANR

Upd: Wir wissen über getItemViewType(pos) Methode und verwenden Sie es an anderen Orten. Aber hier haben wir komplexe Logik, die weiter in 2 verschiedene Bildschirme unterteilt wird, daher haben wir zwei separate Präsentatoren für jeden von RecyclerView und kombinieren sie zu einem und die Trennung in einem Monat ist keine Option.

Von einem Moment an bemerkten wir, dass das Aktualisieren des Bildschirms mit Wischen zum Aktualisieren die Benutzeroberfläche einfriert: übersprungene Frames in Protokollen, Unmöglichkeit, Operationen mit UI durchzuführen, Fortschrittsbalken einzufrieren. Es dauert bis zu fünf Sekunden, aber wir bekommen keine ANR. Es funktioniert am Anfang gut und friert am Ende ein. Wenn wir notifyDataSetChanged() im Adapter entfernen, sieht alles gut aus.

Wir haben versucht, eine der Recycler-Ansichten zu entfernen, um alle Operationen aus ViewHolder.onCreate() und onBindViewHolder() zu entfernen, aber es hat nicht geholfen. Außerdem haben wir überprüft, ob die Probleme durch eine Datenverarbeitung entstehen (wir verwenden RxJava 2, um das Threading zu manipulieren) und wir sehen, dass alle Operationen mit Netzwerk-, Datenbank- und Datenverarbeitung in Nicht-UI-Threads durchgeführt werden und bereits fertig sind wenn die Verzögerung beginnt. Hier

ist das Layout:

<android.support.v4.widget.SwipeRefreshLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    android:id="@+id/swipe_refresh" 
    android:layout_width="match_parent" 
    android:layout_height=«match_parent" 
    android:orientation="vertical" 
    > 
<android.support.v4.widget.NestedScrollView 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content» 
    > 

    <LinearLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:orientation=«vertical" 
     android:paddingBottom="@dimen/spacing_bigger»> 
     <android.support.v7.widget.RecyclerView 
      android:id="@+id/recycle_chats" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:background="@color/white_bg" 
      /> 

     <android.support.v7.widget.RecyclerView 
      android:id="@+id/recycle_friends" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:background="@color/white_bg" 
      /> 

    </LinearLayout> 

</android.support.v4.widget.NestedScrollView> 
</android.support.v4.widget.SwipeRefreshLayout> 

Antwort

2

Es sieht aus wie NestedScrollView mit layout_height="wrap_content" bricht alle Optimierungen von Kindern RecyclerViews. Es gibt ihnen unendlichen Platz unabhängig von den Einschränkungen der übergeordneten Ansicht (SwipeRefreshLayout), die layout_height="match_parent" hat. Als Ergebnis erstellt RecyclerView View-Halter für alle Modelle in Adapter auf einmal. Logging zeigt, dass es für jeden von ihnen 20-60ms dauert, was eine Verzögerung von 2-5 Sekunden für 100 Zeilen bringt.

Wir fügten Protokollierung zu onCreateViewHolder() hinzu und bemerkten, dass es Dutzende (fast hundert) Aufrufe gibt, während es nur ungefähr zehn Elemente auf dem Bildschirm gibt. Das Problem wurde behoben, indem NestedScrollViewlayout_height zu "match_parent" geändert wurde.

+0

Ändern von NestedScrollView's layout_height zu "match_parent" behebt das Problem nicht – Thinsky

+0

Dies ist als akzeptierte Lösung markiert, aber nicht für mich –

0

Warum fügen Sie ein NestedScrollLayout und ein LinearLayout und 2 RecyclerViews hinzu.

All dies kann nur mit der swipeRefreshLayout und RecyclerView erreicht werden

Versuch, der, wie man verschiedene Ansichten auf Position oder Art von Daten basierend hinzuzufügen. Technisch gesehen haben Sie nur einen RecyclerView und einen Adapter, aber der Adapter wird sowohl die Fälle (Freunde und Chats) behandeln als auch Daten an die View (RecyclerView) anhängen.

Und da RecyclerView auch NestedScrollView erweitert ein RecyclerView in einem NestedScrollView halten wird Ihr Scrollen nervös machen, müssen Sie dann IsScrollContainer = True etc. Flags hinzufügen. Also tu es nicht so!

+0

Wir verwenden die getItemViewType(), wo es benötigt wird, aber hier wollten wir in der Lage sein um diese beiden Ansichten einfach in einen anderen Bildschirm zu trennen. Sie haben verschiedene Adapter, Presenter (nach MVP-Muster) und so weiter. Wir werden diesen Bildschirm bald auf kleinere aufteilen, daher war dies der Grund, diese Lösung zu verwenden. – Gaket

1

ich damit auch zu kämpfen hatte, kam schließlich zu dieser Idee, dass ich nicht RecyclerView innen nestedscrollView MIT notifyData richtig so verwenden kann ich es auf diese Weise tat:

I CollapsingToolbarLayout innen AppBarLayout innen CoordinatorLayout setzen. dann habe ich RecyclerView-Header in CollapsingToolbarLayout und die RecyclerView in CoordinatorLayout unter AppBarLayout.

und ich habe auch addOnScrollListener Methode von RecyclerView verwendet, um neue Elemente für RecyclerView nach der Seitenumbruch zu laden.

das ist meine XML-Datei:

<?xml version="1.0" encoding="utf-8"?> 
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/ 
android" 
xmlns:app="http://schemas.android.com/apk/res-auto" 
xmlns:tools="http://schemas.android.com/tools" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:background="#ffffff"> 

<LinearLayout 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 

    <android.support.design.widget.CoordinatorLayout 
     android:layout_width="match_parent" 
     android:layout_height="match_parent"> 

     <android.support.design.widget.AppBarLayout 
      android:id="@+id/activity_txt_news_detail.app_bar_layout" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:background="#00ffffff" 
      app:elevation="0dp"> 

      <android.support.design.widget.CollapsingToolbarLayout 
       android:id="@+id/collapsingToolbarLayout" 
       android:layout_width="match_parent" 
       android:layout_height="match_parent" 
       app:expandedTitleMarginStart="64dp" 
       app:layout_scrollFlags="scroll|snap"> 


       <LinearLayout 
        android:layout_width="match_parent" 
        android:layout_height="wrap_content" 
        android:orientation="vertical"> 

        // all other views 
        // as header of 
        // recyclerview comes here 
       </LinearLayout> 

       <!--todo tgs : here top--> 


      </android.support.design.widget.CollapsingToolbarLayout> 

     </android.support.design.widget.AppBarLayout> 

     <RelativeLayout 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:orientation="vertical" 
      app:layout_behavior="@string/ 
      appbar_scrolling_view_behavior"> 


      <android.support.v7.widget.RecyclerView 
       android:id="@+id/home_news_list" 
       android:layout_width="match_parent" 
       android:layout_height="wrap_content" 
       tools:listitem="@layout/row_news_txt_small" /> 

     </RelativeLayout> 


    </android.support.design.widget.CoordinatorLayout> 
</LinearLayout> 

</FrameLayout> 

diese Zeile Code App: layout_behavior = "@ Zeichenfolge/appbar_scrolling_view_behavior" sehr wichtig ist es in recyclerview Container Layout

bitte informieren Sie mich sein sollte, wenn Es war nützlich für dich. alles Gute

Verwandte Themen