Android RecyclerView Adapter

01.RecyclerView.Adapter扮演的角色

  • 一是,根据不同ViewType创建与之相应的的Item-Layout
  • 二是,访问数据集合并将数据绑定到正确的View上

02.重写的方法

  • 一般常用的重写方法有以下这么几个:

    1
    2
    3
    4
    5
    6
    7
    8
    public VH onCreateViewHolder(ViewGroup parent, int viewType)
    创建Item视图,并返回相应的ViewHolder
    public void onBindViewHolder(VH holder, int position)
    绑定数据到正确的Item视图上。
    public int getItemCount()
    返回该Adapter所持有的Itme数量
    public int getItemViewType(int position)
    用来获取当前项Item(position参数)是哪种类型的布局

03.notifyDataSetChanged()刷新数据

  • 当时据集合发生改变时,我们通过调用.notifyDataSetChanged(),来刷新列表,因为这样做会触发列表的重绘,所以并不会出现任何动画效果,因此需要调用一些以notifyItem*()作为前缀的特殊方法,比如:
    • public final void notifyItemInserted(int position) 向指定位置插入Item
    • public final void notifyItemRemoved(int position) 移除指定位置Item
    • public final void notifyItemChanged(int position) 更新指定位置Item

04.数据变更通知之观察者模式

  • a.首先看.notifyDataSetChanged()源码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    /** @see #notifyItemChanged(int)
    * @see #notifyItemInserted(int)
    * @see #notifyItemRemoved(int)
    * @see #notifyItemRangeChanged(int, int)
    * @see #notifyItemRangeInserted(int, int)
    * @see #notifyItemRangeRemoved(int, int)
    */
    public final void notifyDataSetChanged() {
    mObservable.notifyChanged();
    }
  • b.接着查看.notifyChanged();源码

    • 被观察者AdapterDataObservable,内部持有观察者AdapterDataObserver集合

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      static class AdapterDataObservable extends Observable<AdapterDataObserver> {
      public boolean hasObservers() {
      return !mObservers.isEmpty();
      }

      public void notifyChanged() {
      for (int i = mObservers.size() - 1; i >= 0; i--) {
      mObservers.get(i).onChanged();
      }
      }

      public void notifyItemRangeChanged(int positionStart, int itemCount) {
      notifyItemRangeChanged(positionStart, itemCount, null);
      }

      public void notifyItemRangeChanged(int positionStart, int itemCount, Object payload) {
      for (int i = mObservers.size() - 1; i >= 0; i--) {
      mObservers.get(i).onItemRangeChanged(positionStart, itemCount, payload);
      }
      }

      public void notifyItemRangeInserted(int positionStart, int itemCount) {
      for (int i = mObservers.size() - 1; i >= 0; i--) {
      mObservers.get(i).onItemRangeInserted(positionStart, itemCount);
      }
      }
      }
    • 观察者AdapterDataObserver,具体实现为RecyclerViewDataObserver,当数据源发生变更时,及时响应界面变化

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      public static abstract class AdapterDataObserver {
      public void onChanged() {
      // Do nothing
      }

      public void onItemRangeChanged(int positionStart, int itemCount) {
      // do nothing
      }

      public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
      onItemRangeChanged(positionStart, itemCount);
      }
      }
  • c.接着查看setAdapter()源码中的setAdapterInternal(adapter, false, true)方法

    • setAdapter源码

      1
      2
      3
      4
      5
      6
      public void setAdapter(Adapter adapter) {
      // bail out if layout is frozen
      setLayoutFrozen(false);
      setAdapterInternal(adapter, false, true);
      requestLayout();
      }
    • setAdapterInternal(adapter, false, true)源码

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      private void setAdapterInternal(Adapter adapter, boolean compatibleWithPrevious,
      boolean removeAndRecycleViews) {
      if (mAdapter != null) {
      mAdapter.unregisterAdapterDataObserver(mObserver);
      mAdapter.onDetachedFromRecyclerView(this);
      }
      if (!compatibleWithPrevious || removeAndRecycleViews) {
      removeAndRecycleViews();
      }
      mAdapterHelper.reset();
      final Adapter oldAdapter = mAdapter;
      mAdapter = adapter;
      if (adapter != null) {
      //注册一个观察者RecyclerViewDataObserver
      adapter.registerAdapterDataObserver(mObserver);
      adapter.onAttachedToRecyclerView(this);
      }
      if (mLayout != null) {
      mLayout.onAdapterChanged(oldAdapter, mAdapter);
      }
      mRecycler.onAdapterChanged(oldAdapter, mAdapter, compatibleWithPrevious);
      mState.mStructureChanged = true;
      markKnownViewsInvalid();
      }
  • d.notify……方法被调用,刷新数据

    • 当数据变更时,调用notify**方法时,Adapter内部的被观察者会遍历通知已经注册的观察者的对应方法,这时界面就会响应变更。