Listview-Recyclerview

   @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view = null;
        ViewHolder viewHolder = null;
        //先创建一个内部类,用来放定义控件,然后在if语句中判断converview是否为空,第一次应该是空的,然后绑定id
        if (convertView == null) {
            //实例化view
            view = LayoutInflater.from(context).inflate(R.layout.richang_item, null);
            viewHolder = new ViewHolder();
            viewHolder.tv = view.findViewById(R.id.richang_item_list_tv);
            //将viewHolder打包
            view.setTag(viewHolder);
        } else {
            //第二次直接判断时,converview不为空,直接执行这一步
            view = convertView;
            viewHolder = (ViewHolder) view.getTag();
        }
        //赋值
        viewHolder.tv.setText(dailyList.get(position).getClassifyName());
        return view;
    }

https://blog.csdn.net/u012954720/article/details/80664943
https://blog.csdn.net/u012954720/article/details/80686747

ListView的核心在于layoutChildren函数

makeAndAddView----obtainView----adapter.getView,拿到view之后再使用setupChild加入到ListView里面去并放好位置(包含child自己的measure)

RecycleBin

RecycleBin中 mActiveViews:当前在屏幕上展示的view

mScrapViews :存储滑出屏幕的View; mViewTypeCount>1的时候,ScrapViews数组就会有多个值,分别缓存一个类型的item

mCurrentScrap :和mScrapViews 功能类似,mViewTypeCount=1,也就是listView中只有一种类型的item时(不包括header和footer),item是存入到mCurrentScrap中。

mViewTypeCount : 当前ListView 的item的种类

View的创建以及复用主要是在obtainView中实现
RecyclerBin回收和缓冲机制来展示LsitView

之前我们会在fillActiveViews方法中存储我们目前屏幕中展示的View; 之后又调用了调用了detachAllViewsFromParent()方法,这个方法会将所有ListView当中的子View全部清除掉,从而保证第二次Layout过程不会产生一份重复的数据。

RecycleBin的fillActiveViews()方法来缓存子View,待会儿将会直接使用这些缓存好的View来进行加载,而并不会重新执行一遍inflate过程,因此效率方面并不会有什么明显的影响

滑动过程

incrementalDeltaY 表示触发事件在Y轴上的偏移量,我们会根据他的正负表示向上还是向下滑动,deltaY表示从手指按下到当前手指位置的距离

对于即将要滑出屏幕的数据,使用RecycleBin的addScrapView方法缓存,并且调用detachViewsFromParent将屏幕外的view detach掉,

对于屏幕上的view根据fillGap方法调用fillDown或者fillUp进而调用makeAndAddView,再调用obtinView获取view,最后使用setupChild 将 view 通过attachViewToParent或者addViewInLayout 方法 添加到屏幕上

setAdapter

ListView的setAdapter方法,首先会清楚之前adapter的相关设置,之后重新设置数据观察者,之后再调用requestLayout()

notifyDataSetChanged

requestLayout方法进行重绘

ListView优化

复用contentView

切忌每次 getView()新建,getView方法不能太复杂。ListView的核心原理就是重用View,如果重用view 不改变宽高,重用View可以减少重新分配缓存造成的内存频繁分配/回收

ViewHolder优化使用

ViewHolder的原因是findViewById方法耗时较大,如果控件个数过多,会严重影响性能,而使用ViewHolder主要是为了可以省去这个时间。通过setTag,getTag直接获取View。

减少Item View的布局层级

这是所有Layout都必须遵循的,布局层级过深会直接导致View的测量与绘制浪费大量的时间。

图片加载采用三级缓存,避免每次都要重新加载。
尝试开启硬件加速来使ListView的滑动更加流畅。

RecyclerView

mAttachedScrap: 用于缓存显示在屏幕上的 item 的 ViewHolder

mCachedViews:这个就重要得多了,滑动过程中的回收和复用都是先处理的这个 List,这个集合里存的 ViewHolder 的原本数据信息都在,所以可以直接添加到 RecyclerView 中显示,不需要再次重新 onBindViewHolder()

RecyclerViewPool

回收复用过程

mCachedViews默认大小为2,RecyclerViewPool 为5

mCachedViews 优先级高于 RecyclerViewPool,回收时,最新的 ViewHolder 都是往 mCachedViews 里放,如果它满了,那就移出一个扔到 ViewPool 里好空出位置来缓存最新的 ViewHolder。

复用时,也是先到 mCachedViews 里找 ViewHolder,但需要各种匹配条件,概括一下就是只有原来位置的卡位可以复用存在 mCachedViews 里的 ViewHolder,如果 mCachedViews 里没有,那么才去 ViewPool 里找。

在 ViewPool 里的 ViewHolder 都是跟全新的 ViewHolder 一样,只要 type 一样,有找到,就可以拿出来复用,重新绑定下数据即可

先复用再回收

优化方案和使用技巧

recyclerView.setHasFixedSize(true)

当Item的高度如是固定的,设置这个属性为true可以提高性能,尤其是当RecyclerView有条目插入、删除时性能提升更明显

RecyclerView在条目数量改变,会重新测量、布局各个item,如果设置了setHasFixedSize(true),由于item的宽高都是固定的,adapter的内容改变时,RecyclerView不会整个布局都重绘

使用getExtraLayoutSpace为LayoutManager设置更多的预留空间

在RecyclerView的元素比较高,一屏只能显示一个元素的时候,第一次滑动到第二个元素会卡顿

RecyclerView (以及其他基于adapter的view,比如ListView、GridView等)使用了缓存机制重用子 view(即系统只将屏幕可见范围之内的元素保存在内存中,在滚动的时候不断的重用这些内存中已经存在的view,而不是新建view)

这个机制会导致一个问题,启动应用之后,在屏幕可见范围内,如果只有一张卡片可见,当滚动的时 候,RecyclerView找不到可以重用的view了,它将创建一个新的,因此在滑动到第二个feed的时候就会有一定的延时,但是第二个feed之 后的滚动是流畅的,因为这个时候RecyclerView已经有能重用的view了。

如何解决这个问题呢,其实只需重写getExtraLayoutSpace()方法

LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this) {
    @Override
    protected int getExtraLayoutSpace(RecyclerView.State state) {
        return 300;
    }
};
RecyclerView 数据预取
避免创建过多对象
局部刷新

notifyItemChanged(int position)

如果必须用 notifyDataSetChanged(),那么最好设置 mAdapter.setHasStableIds(true)

重写onScroll事件

对于大量图片的RecyclerView,滑动暂停后再加载

RecyclerView与ListView对比

二级缓存
四级缓存

RecyclerView与ListView缓存机制的不同

想改变listview的高度,怎么做?

     ViewGroup.LayoutParams params = listView.getLayoutParams();

      params.height = totalHeight; 
      
      listView.setLayoutParams(params);

listview跟recyclerview上拉加载的时候分别应该如何处理?

如何自己实现RecyclerView的侧滑删除?

RecyclerView的ItemTouchHelper的实现原理

RecyclerView 滑动控制笔记

https://www.jianshu.com/p/e8117855c6a0
https://www.jianshu.com/p/055fa3cb964e
https://www.jianshu.com/p/d8379a77a782
]
recyclerview性能优化
https://www.jianshu.com/p/eabb00c500ef
尽量将复杂的数据处理操作放到异步中完成
优化RecyclerView的布局,避免将其与ConstraintLayout使用
如果ItemView的高度固定,可以使用setHasFixSize(true)
当UI是Tab feed流时,可以考虑使用RecycledViewPool来实现多个RecyclerView的缓存共享。

viewholder类的使用,减少查找控件的次数(findviewbyid()次数),将holder与view绑定来实现(.setTag()、.getTag())

实现控件之间的联动

Behavior

ListView采用的是RecyclerBin的回收机制在一些轻量级的List显示时效率更高

listview和recyclerview区别

1、recyclerview功能更强大,支持竖直、水平,gridview、瀑布流,局部刷新、局部删除,动画

2、listview要自定义viewholder,recyclerview 已经定义好了viewholder

3、缓存

RecyclerView
https://blog.csdn.net/weixin_44339238/article/details/108654771

RecyclerView.ItemAnimator
https://blog.csdn.net/zxm317122667/article/details/51502377

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值