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博客