面试:List View和RecyclerView缓存策略对比

发布于:2022-11-05 ⋅ 阅读:(475) ⋅ 点赞:(0)

Listview的二级缓存

ListView 是怎么实现 RecycleBin 并更新 View 的?

在 Adapter 中的 getView()方法中执行 LayoutInflater.inflate()方法是很消耗资源的,所以ListView通过 RecycleBin 去维护两个数组 mActiveViews 和mScrapViews 用来进行 view 的复用工作。具体是在绘制 view 的(measure->layout->draw)的 layout 过程中实现。
举个例子,某一时刻ListView中显示10个子View,position依次是0-9,这时下滑,ListView需要绘制下一帧,这时候ListView在layoutchildren方法中把这10个子View都存入了mActiveViews数组中,然后清空children数组,调用filldown方法,向listview中依次添加position 1到10的子view,在填充1-9时,由于在上一帧position=1-9的view已经被放入了mActiveViews数组中,因此可以直接将其从数组中取出,直接复用。如果没能够从mActivieViews中直接复用View,那么就要调用obtainView方法获取View,该方法尝试间接复用RecycleBin中的mScrapViews中的View,如果不能间接复用,则创建新的View。

ListView的缓存和复用由它的父类AbsListView中的RecycleBin实现,设了两个缓存数组mActiveViews和mScrapViews。mActiveViews缓存显示在屏幕中的view,mScrapViews按ViewType缓存离屏的view

RecycleBin作为实现类:通过两级缓存来缓存view。

ActiveViews存储的是layout开始的时候屏幕上那些view。layout结束后,所有ActiveViews中的view被移动到ScrapViews中。

ScrapViews中的views是那些可能被adapter重新用到的view,以避免重新创建不必要的view。

在这里插入图片描述

ListView 怎么进行优化的?

ConvertView重用机制:在getView()方法中使用ConvertView,不需要每次都inflate一个View出来,这样既浪费时间又浪费内存。
Viewholder机制:使用Viewholder,避免在getView()方法频繁调用去使用findViewById方法,节省时间和内存。
分页加载:每加载一页的数据就覆盖上一页的数据。
数据中有图片:使用第三方库(三级缓存机制)

@Override
    public View getView(int position, View convertView, ViewGroup viewGroup) {
        LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
        if (getItemViewType(position) == ViewType.TEXT){
            if (convertView == null){
                convertView = inflater.inflate(R.layout.text_message_item,viewGroup,false);
            }
            TextView textView = convertView.findViewById(R.id.message_content);
            TextMessage textMessage = (TextMessage)messageList.get(position);
            textView.setText(textMessage.getText());
        }else {
            if (convertView == null){
                convertView = inflater.inflate(R.layout.image_message_item,viewGroup,false);
            }
            ImageView imageView = convertView.findViewById(R.id.image_head);
            ImageMessage imageMessage = (ImageMessage)messageList.get(position);
            imageView.setImageResource(imageMessage.getImage());
        }
        return convertView;
    }

RecyclerView的四级缓存

RecycleView的四级缓存是由三个类共同作用完成的,Recycler、RecycledViewPool和ViewCacheExtension。

一、Recycler

​ 用于管理已经废弃或者与RecyclerView分离的ViewHolder

1.屏幕内缓存 一级缓存,屏幕内缓存指在屏幕中显示的ViewHolder,这些ViewHolder会缓存在AttachedScrap、ChangedScrap中

2.屏幕外缓存 二级缓存,当列表滑动出了屏幕时,ViewHolder会被缓存在 CachedViews ,其大小由ViewCacheMax决定,默认DEFAULT_CACHE_SIZE为2,可通过Recyclerview.setItemViewCacheSize()动态设置。

二、RecycledViewPool

​ 三级缓存, RecycledViewPool类是用来缓存ViewHolder

三、ViewCacheExtension

四级缓存, 开发者可自定义的一层缓存,是虚拟类ViewCacheExtension的一个实例,开发者可实现方法getViewForPositionAndType(Recycler recycler, int position, int type)来实现自己的缓存。

 RecyclerView的缓存和复用由Recycler实现,mAttachedScrap和mCachedViews的缓存方式跟ListView相似。mRecyclerPool是多个RecyclerView的复用池,mViewCacheExtension不直接使用,需要用户再定制,默认不实现。

public final class Recycler {
    final ArrayList<ViewHolder> mAttachedScrap = new ArrayList<>();
    final ArrayList<ViewHolder> mCachedViews = new ArrayList<ViewHolder>();
    RecycledViewPool mRecyclerPool;
    private ViewCacheExtension mViewCacheExtension;
}

总结

ListView二级缓存

 RecyclerView四级缓存

【Android面试】Listview和Recyclerview的区别_Rose J的博客-CSDN博客_android listview和recyclerview Android:ListView 和RecyclerView区别 - 夜空中最亮的盖子 - 博客园

Android 实习生面试经历记录_code小生_的博客-CSDN博客

 


网站公告

今日签到

点亮在社区的每一天
去签到