美文网首页View源码解析
ListView的复用和缓存机制

ListView的复用和缓存机制

作者: jacky123 | 来源:发表于2016-07-18 22:21 被阅读1108次

    复用分析

    **1. 在AbListView中 **

    /**
     * The data set used to store unused views that should be reused during the next layout
     * to avoid creating new ones
     */
    final RecycleBin mRecycler = new RecycleBin();
    

    RecycleBin包含了两个级别的存储,ActiveViews和ScrapViews,ActiveViews存储的是第一次显示在屏幕上的View;所有的ActiveViews最终都会被移到ScrapViews,ScrapViews存储的是有可能被adapter复用的View。

    **2. 在ListView的LayoutChildren 中 **

    @Override
    protected void layoutChildren() 
    {
        if (dataChanged) 
        {
            for (int i = 0; i < childCount; i++) 
            {
                recycleBin.addScrapView(getChildAt(i));   
            }
        } else 
        {
            recycleBin.fillActiveViews(childCount, firstPosition);
        }
        ....
    }
    

    可以看出,如果数据发生变化则把当前的ItemView放入ScrapViews中,否则把当前显示的ItemView放入ActiveViews中。

    3. 那么咱们关键的getView方法到底是在哪调用呢
    在AbsListView中我们看obtainView中的方法:

    /**
     * Get a view and have it show the data associated with the specified
     * position. This is called when we have already discovered that the view is
     * not available for reuse in the recycle bin. The only choices left are
     * converting an old view or making a new one.
     *
     * @param position The position to display
     * @param isScrap Array of at least 1 boolean, the first entry will become true if
     *                the returned view was taken from the scrap heap, false if otherwise.
     * 
     * @return A view displaying the data associated with the specified position
     */
    View obtainView(int position, boolean[] isScrap) 
    {
        final View scrapView = mRecycler.getScrapView(position);
        final View child = mAdapter.getView(position, scrapView, this);
        if (scrapView != null) {
            if (child != scrapView) {
                // Failed to re-bind the data, return scrap to the heap.
                mRecycler.addScrapView(scrapView, position);
            } else {
                isScrap[0] = true;
    
                child.dispatchFinishTemporaryDetach();
            }
        }
    
        return child;
    }
    

    可以看到,这个方法就是返回当前一个布局用户当前Item的显示,首先根据position去ScrapView中找,找到后调用我们的getView,此时getView里面的convertView!=null了,然后getView如果返回的View发生变化,缓存下来,否则convertView==null了。

    参考资料

    相关文章

      网友评论

        本文标题:ListView的复用和缓存机制

        本文链接:https://www.haomeiwen.com/subject/bjcmjttx.html