Constitute a

  • ListView
    • View+Adapter
  • RecyclerView
    • View+Adapter+LayoutManager

Difference between ListView and RecyclerView

  • The measurement and layout of RecyclerView are handled by LayoutManager
    • RecyclerView is responsible for touch feedback management, layout control has a special LayoutManager.
  • In terms of recycling, RecyclerView uses ViewHolder, and ListView uses View (generally, handwritten Holder is used to reduce the repetitive work of FindViewById).
  • There are two levels of caching in ListView, and most of the time only one of them is in effect.
  • In RecyclerView, Scrap, Cache and Pool will frequently participate in the reuse mechanism. It is also possible to implement caching for specific policies through custom caches (there is just no exact usage scenario or application).
  • RecycerlView RecycledViewPool can make multiple RecyclerView common a Pool to greatly improve reuse efficiency.

Recycling reuse

  • ListView is responsible for cache management object is Recyclerbin, including two levels of cache
    • MScrapViews mActiveViews [] and ArrayList []
      • MActiveViews refers to views visible on the screen
      • MScrapViews can be interpreted as views that are not on the screen
        • The reason we declare a List as an array is because we’re thinking about viewTypes, different item types
  • RecyclerView The Recycler is used for cache management, which corresponds to Recyclerbin in ListView. The four-level cache is as follows
        final ArrayList<ViewHolder> mAttachedScrap = new ArrayList<>();
        ArrayList<ViewHolder> mChangedScrap = null;
    
        final ArrayList<ViewHolder> mCachedViews = new ArrayList<ViewHolder>();
        RecycledViewPool mRecyclerPool;
    Copy the code

RecyclerView simple operation mechanism

  • LayoutManager will only request Recycler view
  • OnCreaterViewHolder is called by Recycler, and Adapter returns the ViewHolder

From Listview to RecyclerView

  • Animation on ListView is a hassle, so that’s one of the reasons RecyclerView was introduced
  • ListView animation trouble, because do not know which specific views have changed, so that can not do local refresh
  • Local refresh on RecyclerView becomes simple

ListView reuse mechanism

  • The role mActiveViews [] : When ListView data has not changed, ListView has rearranged the layout(), the child elements in mActiveViews a store a fetch, to achieve fast reuse effect, reuse efficiency is relatively high, ListView does not need to call our rewrite getView method, Neither onCreate nor onBind needs to be executed
    • The usage of mActiveViews is very low. Due to historical reasons, when the SDK version is very low, the ListView will layout several times. At this time, mActiveViews effectively improves the efficiency
  • ArrayList[] mScrapViews: notifyDataSetChanged and notifyDataSetChanged interact with mScrapViews both on and off slide
    • What is displayed on the screen
      • Each list in the array corresponds to a set of views in the viewType
      • Each view is added to the cache and retrieved at binding time
      • As shown in figure
    • Slip condition
      • Once the view slides out of the view, it gets cached
      • Once it slides into the screen, it takes it out of the cache
      • If it’s not in cache
      • As shown in figure
  • ListView reuse logic summary
    • Get it from mActiveViews first
    • If not, pull it from mScrapViews
    • If not, create a new view to return to use

Four level cache in RecyclerView

  • mCachedViews
    • The main purpose is to optimize performance when sliding. By default, only two viewholders can be stored. You can customize the volume by setItemViewCacheSize
    • Swiping up the screen, position0 and position1 are saved to mCachedViews when items are removed from the screen
    • If you swipe down, position1 will reappear on the screen, and mCachedViews will be used to see if there is a view with position1 in cache
    • The cache of mCachedViews is not classified by viewType, which means that viewHolder of different types can be stored in mCachedViews, which means that the slide in and slide out operation above does not execute onBindViewHolder
    • As a result of the pull-down, position6 is removed from the screen and stored in mCachedViews
  • Recycling pool mRecyclerPool
    • In the above operation, if position2 is removed from the screen, it is added to mCachedViews, and position0 is squeezed out and added to the mRecyclerPool
    • Data structure:
      • Member variable mScrap in mRecyclerPool
      • DEFAULT_MAX_SCRAP Indicates that each viewType can cache a maximum of five views by default. You can use setMaxRecycledViews to specify the maximum value
      private static final int DEFAULT_MAX_SCRAP = 5;
      static class ScrapData {
              ArrayList<ViewHolder> mScrapHeap = new ArrayList<>();
              int mMaxScrap = DEFAULT_MAX_SCRAP;
              long mCreateRunningAverageNs = 0;
              long mBindRunningAverageNs = 0;
          }
      SparseArray<ScrapData> mScrap = new SparseArray<>();
      Copy the code
    • If you keep swiping, position1 and position2 come back to the screen and are retrieved from mCachedViews. Position6 and position7 slide off the screen and enter mCachedViews. If you keep swiping down, position0 is retrieved from the recycle pool
    • MRecyclerPool relative to ListView mScrapViews optimization
      • Support multiple RecyclerView to share the same recycling pool
      • The cache capacity can be set separately according to the viewType and optimized accordingly
      • Since the values of viewType are no longer the index of the array, they do not need to be consecutive. We can write r.layout. XXX as the viewType
  • MAttachedScrap staging area
    • MAttachedScrap deposit
    • RecyclerView to obtain the cache order,
      • Take it from the mAttachedScrap hold area first
      • And then the mCachedViews
      • And then the mRecyclerViewPool
    • Different from mCachedViews, as a temporary storage area of viewHodler, viewholder will only be temporarily saved in a layout process. At the beginning of the layout, RecyclerView will store all the layouts into mAttachedScrap and at the end of the layout. Even if a Viewholder is still in the staging area, it is thrown into the recycle pool
  • MChangedScrap staging area
    • The viewHolder whose data has changed goes into the mChangedScrap hold area

Core mechanics pre-layout/post-layout

When RecyclerView supports pre/post-layout mechanism, it can specify the position of all ItemView before and after data changes, so that predictive animation can be easily made.

  • RecyclerView provides animation for us when deleting item, inserting item and changing item, so how to realize animation
  • Predictive animation: notifyItemRemoved Animation principle
    • As shown in figure
    • Taking notifyItemRemoved as an example, B gradually disappears and performs the entrance animation, while C gradually displays and performs the entrance animation
    • The adapter notifying that B is removed, so the pre-layout can judge that C is to be displayed by the notification that B is removed, and C will be placed during the pre-Layout. Once it is placed, the starting point of the animation can be determined
    • Because of this mechanism, RecyclerView makes it easy to do predictive animation
  • Local refresh: notifyItemSetChanged
    • NotifyItemSetChanged is actually animating two items. The old item gradually becomes opaque and the new item gradually becomes transparent. This seems to violate the principle of local refreshes, but it is, and this is why we often find the image flickering in local refreshes
    • The reason for doing this is that there is a scenario in which all the data of the item to be changed is changed, so the whole item needs to be changed. By default, the completely replacement method is used in RecyclerView
  • Efficient local refresh: Two ways to prevent the flicker of local refresh images
    • A: you can use setSupportChangeAnimations (false) to prohibit predictive animation, but this way will disable remove animations and inserted into the animation
    • Payload ->notifyItemChanged(position,"payload");

RecyclerView reuse strategy

  1. Scrap in an attempt to obtain
    • If the obtained data does not need to be rebound, directly use
  2. The value was obtained from the Cache. Procedure
    • If the obtained data does not need to be rebound, directly use
  3. Try to fetch in custom cache (actually find no meaningful application)
  4. The value was obtained from the Pool. Procedure
    • You need to rebind the data to use it except in special cases