Android ListView RecycleBin(View 回收利用)机制

    一直都知道ListView  有View回收再利用的机制,一直都是去判断getView函数中的 convertView是否为null从而确定是否要重新创建View, 一直都是这么用也没有多想原理是什么

    今天开发过程中涉及到ListView中 显示多个种类的View,只是简单判断convertView是否为空肯定会出错,就算加上判断View是否是我们需要的种类,那么也还是会一定程度上降低效率(重新创建View的几率会很大)

     想来想去一直这么迷迷糊糊下去也不是回事,决定去研究下源代码

 

     ListView的父类是AbsListView,AbsListView 里面有个子类 RecycleBin,ListView中的 View就是在此处管理的

     

     RecycleBin 类中的 三个变量涉及到此处的解析

        private ArrayList[] mScrapViews;  这个就是用来记录所有被回收的 View的地方

        private int mViewTypeCount; 这个用于记录有多少种类的View

        private ArrayList mCurrentScrap; 这个很好理解  字面意思 当前的记录列表

 

    其他的我们不看,比如这个View是怎么加进去之类的,我们就看看这个View是怎么获得 并传递到getView的 convertView的参数上的

 

    其中 mViewTypeCount 的赋值操作:

    public void setViewTypeCount(int viewTypeCount) 

 

    在ListView的setAdapter函数中有调用到这个函数

    @Override

    public void setAdapter(ListAdapter adapter) {

        ---省略代码---

        if (mAdapter != null) {

            ---省略代码---

            mRecycler.setViewTypeCount(mAdapter.getViewTypeCount());

        ---省略代码---

    }

 

    由上面可以看出 viewTypeCount的值出自于 ListAdapter 也就是我们要在ListAdapter函数中实现getViewTypeCount()函数,返回我们的View种类

 

    View种类的问题解决 我们看看这个种类是怎么用的,首先我们来看ListAdapter 的getView函数的调用的地方

    View obtainView(int position, boolean[] isScrap) {

        ---省略代码---

        scrapView = mRecycler.getScrapView(position);

        View child;

        if (scrapView != null) {

            child = mAdapter.getView(position, scrapView, this);

            ---省略代码---

        } else {

            child = mAdapter.getView(position, null, this);

            ---省略代码---

        }

        ---省略代码---

    }

 

    我们看到在调用getView的地方调用了RecycleBin类中getScrapView函数

        /**

         * @return A view from the ScrapViews collection. These are unordered.

         */

        View getScrapView(int position) {

            if (mViewTypeCount == 1) {

                return retrieveFromScrap(mCurrentScrap, position);

            } else {

                int whichScrap = mAdapter.getItemViewType(position);

                if (whichScrap >= 0 && whichScrap < mScrapViews.length) {

                    return retrieveFromScrap(mScrapViews[whichScrap], position);

                }

            }

            return null;

        }

 

       我们看到 int whichScrap = mAdapter.getItemViewType(position);这句调用就是获取 View种类的地方

       同样我们要在ListAdapter中实现getItemViewType(position) 这个函数,根据位置信息 我们判断类表相应位置的数据需要的View种类

 

       那么我们现在知道了通过在ListAdapter函数中实现 getItemViewType(position) 和getViewTypeCount()函数,便能够实现不同种类的View的循环再利用了

 

 

 

      另外通过这次解析ListView中有个监听View被回收的接口

      public void setRecyclerListener(RecyclerListener listener)

     

      public static interface RecyclerListener {

        /**

         * Indicates that the specified View was moved into the recycler's scrap heap.

         * The view is not displayed on screen any more and any expensive resource

         * associated with the view should be discarded.

         *

         * @param view

         */

        void onMovedToScrapHeap(View view);

    }

 

     通过这个接口我们能知道那个view被回收了,我们可以在此处做一些释放内存的操作,比如View中包含了ImageView,那么我们就可以在此处把ImageView中使用的Bitmap干掉,如果达到了一定的数量级这个地方会非常有用

 

你可能感兴趣的:(Android ListView RecycleBin(View 回收利用)机制)