RecyclerView(局部刷新) 和 ListView(优化)的区别,ExpandableListView,ListView禁止上下滚动

本文主要是介绍RecyclerView(局部刷新) 和 ListView(优化)的区别,ExpandableListView,ListView禁止上下滚动,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

根据自己的使用场景来选择是要用 RecyclerView 还是 ListView- https://github.com/D-clock/AndroidSystemUiTraining
-- RecyclerView 相比 ListView 在基础使用上的区别主要有如下几点:
  1.ViewHolder 的编写规范化了
  2.RecyclerView 复用 Item 的工作 Google 全帮你搞定,不再需要像 ListView 那样自己调用 setTag

  3.RecyclerView 需要多出一步 LayoutManager 的设置工作

--  监听RecyclerView列表划过的位置 Android
scrollview监听滑动位置- https://blog.csdn.net/shb2058/article/details/50707221
android 检测ListView滚动到的位置- http://www.mamicode.com/info-detail-121427.html
android仿朋友圈列表精准定位- https://www.jianshu.com/p/c741a0488a70

-- ListView 和 RecyclerView 复用机制区别- https://www.jianshu.com/p/1eaaccd169e4
 ListView 的复用是两级缓存的,而 RecyclerView 是四级缓存;
 ListView 复用的是 View,也就是在实现 ListView 的 Adapter 的时候实现的 getView 方法里的参数 convertView,但是 RecyclerView 复用的对象是 ViewHolder,当然 ListView 也可以由自己来实现 ViewHolder;
  ListView 的回收过程十分简单,就是完全滑出屏幕后就把 View 回收到 mScrapeViews 当中去,并把 View 还原成初始状态,所以说 ListView 中所有进行复用的 View 的数量加起来一定是一个定值,其大小和屏幕所能容纳下的 item 的个数有关
  RecyclerView 的回收过程就是一个标准的二级缓存,滑出屏幕的 ViewHolder 先缓存进 mCacheViews ,此时并不还原视图,当 mCacheViews 中的数量超过一定的限制以后(默认是2个,这个是可以由自己来决定的),将最先放入 mCacheViews 的 ViewHolder 放入到 mRecyclerPool 当中去,并且是根据 View 的 type 不同,放入不同的 mRecyclerPool 当中去,同时 mRecyclerPool 也有大小的限制(默认是 5 个),但是这种回收机制好处就在于可以保证 mCacheViews 和 mRecyclerPool 是最新的放到前面。

> RecyclerView 

RecyclerView添加头部和尾部- https://github.com/jdsjlzx/LRecyclerView

RecyclerView添加头部和尾部- https://github.com/whichname/PTLRecyclerView

为RecyclerView添加HeaderView和FooterView- http://blog.csdn.net/lmj623565791/article/details/51854533
 Android 默认提供的 RecyclerView 就能支持 线性布局、网格布局、瀑布流布局 三种(这里我们暂且不提代码细节,后文再说),而且同时还能够控制横向还是纵向滚动。怎样,从效果上足以碾压 ListView 有木有。

LayoutManager 只是一个抽象类而已,系统已经为我们提供了三个相关的实现类:
  1.横向滚动的ListView开源控件是不是可以不用再找了?对,你没看错!- LinearLayoutManager(线性布局效果)
  2.瀑布流效果的开源控件是不是可以不用再找了?对,你没看错!- GridLayoutManager(网格布局效果)
  3.连横向滚动的GridView都不用找了!对,你没看错!-StaggeredGridLayoutManager(瀑布流布局效果)
-- RecyclerView 基础使用关键点同样有两点:
  继承重写 RecyclerView.Adapter 和 RecyclerView.ViewHolder;
  设置布局管理器,控制布局效果

-- 系统也为我们提供了两个默认的动画实现:SimpleItemAnimator 和 DefaultItemAnimator。而 RecyclerView 在不手动调用 setItemAnimator 的情况下,则默认用了内置的 DefaultItemAnimator 。

-- RecyclerView管理器:
1.LinearLayoutManager 现行管理器,支持横向、纵向。
2.GridLayoutManager 网格布局管理器
3.StaggeredGridLayoutManager 瀑布就式布局管理器
-- RecyclerView整体总结它的几点如下:
 Adapter:包装数据集合并且为每个条目创建视图。
 ViewHolder:保存用于显示每个数据条目的子View。
 LayoutManager:将每个条目的视图放置于适当的位置。
 ItemDecoration:在每个条目的视图的周围或上面绘制一些装饰视图。
 ItemAnimator:在条目被添加、移除或者重排序时添加动画效果。

-- RecyclerView 数据刷新的几种方式,RecyclerView 真正的布局刷新的正确方式
再说Android RecyclerView局部刷新那个坑- https://blog.csdn.net/jdsjlzx/article/details/52893469
RecyclerView之更新UI数据的高级用法- https://blog.csdn.net/leejizhou/article/details/51179233

notifyDataSetChanged(),刷新全部可见的item

notifyItemChanged(int position) 更新列表position位置上的数据可以调用
notifyItemInserted(int position) 列表position位置添加一条数据时可以调用,伴有动画效果
notifyItemRemoved(int position) 列表position位置移除一条数据时调用,伴有动画效果
notifyItemMoved(int fromPosition, int toPosition) 列表fromPosition位置的数据移到toPosition位置时调用,伴有动画效果
notifyItemRangeChanged(int positionStart, int itemCount) 列表从positionStart位置到itemCount数量的列表项进行数据刷新
notifyItemRangeInserted(int positionStart, int itemCount) 列表从positionStart位置到itemCount数量的列表项批量添加数据时调用,伴有动画效果
notifyItemRangeRemoved(int positionStart, int itemCount) 列表从positionStart位置到itemCount数量的列表项批量删除数据时调用,伴有动画效果

-- RecyclerView清除缓存,Fragment中的刷新
Fragment中的刷新问题- https://blog.csdn.net/qq_27969037/article/details/53555884
RecyclerView 局部刷新Item卡顿,已解决- https://blog.csdn.net/weixin_39079048/article/details/79448344
adapter试下remove后,再insert。

-- 使用https://github.com/whichname/PTLRecyclerView库,adapter里面的notify一系列方法,好多都失效,除了load的时候能完成部分效果外,绝大部分效果并不支持,比如元素删除、插入等
由于头部其实也是item,因此使用notify时,需通过adapter获取item真实的位置来进行更新

-- RecyclerView缓存,RecyclerView缓存清理,RecyclerView的重用机制
RecyclerView解决条目错乱以及图片闪越+三级缓存机制- https://blog.csdn.net/haoxl1994/article/details/59095522
 - 解决recyclerView加载图片闪越问题和图片错乱的问题:
 图片闪越:在onBindView方法中给图片设置站位图
 图片错乱:一种是在onViewRecycle方法中取消加载的图片的异步任务,第二种是在onBindViewHolder方法中给ImageView设置Tag,在设置图片的时候判断Tag如果没有变化才设置图片。

 - RecyclerView缓存机制总结:主要是三步:
主要靠三个内部类来完成,Recycler,ViewCacheExtension,RecyclerViewPool:
 1、首先通过 recycler.getViewForPosition()方法,该方法返回ViewHolder对象,通过源码可以知道,该方法会检查mAttachedScrap和一级
缓存列表mCachedViews,如果有则返回ViewHolder进行复用。
 2、然后调用ViewCacheExtension.getViewForPositionAndType()方法,注意这个方法是抽象方法,需要开发者进行重写。
 3、最后检查RecyclerViewPool是否有ViewHolder。
 注意:上述的三个步骤中,只要有一个返回了ViewHolder,就不会在进行后边的步骤了。
 最后:缓存的数量:默认的一级缓存中,mCachedViews中可以缓存的ViewHolder的个数是2;默认的缓存池中的缓存数量是 5;所以在缓存时
,会先检测一级缓存是否满了,如果没满就add进去,如果满了就加入到三级缓存Recyclerpool
recyclerView的Item局部更新问题:http://www.tuicool.com/articles/euuy2iM

-- RecyclerView的绘制流程关键点:
 1.RecyclerView是将绘制流程交给LayoutManager处理,如果没有设置不会测量子View。
 2.绘制流程是区分正向绘制和倒置绘制。
 3.绘制是先确定锚点,然后向上绘制,向下绘制,fill()至少会执行两次,如果绘制完还有剩余空间,则会再执行一次fill()方法。
 4.LayoutManager获得View是从RecyclerView中的Recycler.next()方法获得,涉及到RecyclerView的缓存策略,如果缓存没有拿到,则走我们自己重写的onCreateView方法。
 5.如果RecyclerView宽高没有写死,onMeasure就会执行完子View的measure和Layout方法,onLayout仅仅是重置一些参数,如果写死,子View的measure和layout会延后到onLayout中执行。

基于AOP的RecyclerView楼层开发方式,支持组件化工程,全局多人楼层打通,高拓展性- https://github.com/DrownCoder/EMvp

 视图的复用机制,也就是缓存。从ListView的RecycleBin到RecyclerView的Recycler,Google对于列表视图的缓存的设计一直非常考究值得我们学习和研究。

RecyclerView类的结构也比较清楚,这里可以清楚的看到我们后面讲到的四级缓存机制所用到的类都在这里可以看到:
    * 1.一级缓存:mAttachedScrap
    * 2.二级缓存:mCacheViews
    * 3.三级缓存:mViewCacheExtension
    * 4.四级缓存:mRecyclerPool
1.RecyclerView内部大体可以分为四级缓存:mAttachedScrap,mCacheViews,ViewCacheExtension,RecycledViewPool.
2.mAttachedScrap,mCacheViews在第一次尝试的时候只是对View的复用,并且不区分type,但在第二次尝试的时候是区分了Type,是对于ViewHolder的复用,ViewCacheExtension,RecycledViewPool是对于ViewHolder的复用,而且区分type。
3.如果缓存ViewHolder时发现超过了mCachedView的限制,会将最老的ViewHolder(也就是mCachedView缓存队列的第一个ViewHolder)移到RecycledViewPool中。

> ListView 

- ListView图片错乱问题,在getview方法中给imageview设置tag,这个tag可以为url
ImageView.setTag(imageUrl);

- 如果要给 ListView 的 Item 加动画,我们只能自己通过属性动画来操作 Item 的视图: https://github.com/nhaarman/ListViewAnimations
-- ListView 的基础使用大家再熟悉不过,其使用的关键点主要如下:
  继承重写 BaseAdapter 类;自定义 ViewHolder 和 convertView 一起完成复用优化工作
-- ListView 提供了 setEmptyView 这个 API 来让我们处理 Adapter 中数据为空的情况,只需轻轻一 set 就能搞定一切。代码设置和效果如下
        mListView = (ListView) findViewById(R.id.listview);

        mListView.setEmptyView(findViewById(R.id.empty_layout));//设置内容为空时显示的视图

[Android优化进阶] 提高ListView性能的技巧 -- http://www.jianshu.com/p/3e22d53286ca#
ListView优化一直是一个老生常谈的问题,不管是面试还是平常的开发中,ListView永远不会被忽略掉,那么这篇文章我们来

-- 如何最大化的优化ListView的性能:
2.尽最大可能避免GC
3.滑动的时候不加载图片
4.将ListView的scrollingCache和animateCache设置为false

5、convertView重用;
 利用好 convertView 来重用 View,切忌每次 getView() 都新建。ListView 的核心原理就是重用 View,如果重用 view 不改变宽高,重用View可以减少重新分配缓存造成的内存频繁分配/回收;
6、ViewHolder优化;
 使用ViewHolder的原因是findViewById方法耗时较大,如果控件个数过多,会严重影响性能,而使用ViewHolder主要是为了可以省去这个时间。通过setTag,getTag直接获取View。
7、图片加载优化
 如果ListView需要加载显示网络图片,我们尽量不要在ListView滑动的时候加载图片,那样会使ListView变得卡顿,所以我们需要在监听器里面监听ListView的状态,如果ListView滑动(SCROLL_STATE_TOUCH_SCROLL)或者被猛滑(SCROLL_STATE_FLING)的时候,停止加载图片,如果没有滑动(SCROLL_STATE_IDLE),则开始加载图片。
8、onClickListener处理(通过接口回传)
9、减少Item View的布局层级
 这是所有layout都必须遵循的,布局层级过深会直接导致View的测量与绘制浪费大量的时间
10、adapter中的getView方法尽量少使用逻辑
 不要在getView方法中做过于复杂的逻辑,可以想办法抽离到别的地方,
11、adapter中的getView方法尽量少做耗时操作
12、adapter中的getView方法避免创建大量对象
13、将ListView的scrollingCache和animateCache设置为false
14、分页加载数据

-- ListView优化方案-http://blog.csdn.net/fenghai22/article/details/44173057

一、复用convertView,减少findViewById的次数 
1、优化一:复用convertView
2、优化二:缓存item条目的引用——ViewHolder

二、ListView中数据的分批及分页加载:

三、ListView中图片的优化:详看OOM异常中图片的优化 ,压缩及三级缓存

四、ListView的其他优化:
1、尽量避免在BaseAdapter中使用static 来定义全局静态变量: 
2、尽量使用getApplicationContext: 
3、尽量避免在ListView适配器中使用线程:

-- ListView禁止上下滑动
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ListView;

public class ScrollEnableListView extends ListView {

    private int mPosition;
    private boolean mIsScroll = true;

    /**
     * 是否支持上下滑动
     *
     * @param isScroll 滑动与否, true可以滚动
     */
    public void setScrollEnable(boolean isScroll) {
        mIsScroll = isScroll;
    }

    public ScrollEnableListView(Context context) {
        super(context);
    }

    public ScrollEnableListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ScrollEnableListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        ToastUtil.showToast("ListView onMeasure");
        if (!mIsScroll) {
            int expandSpec = MeasureSpec.makeMeasureSpec(
                    Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
            super.onMeasure(widthMeasureSpec, expandSpec);
        } else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        ToastUtil.showToast("ListView dispatchTouchEvent");
        if (!mIsScroll) {
            return true;
        }
        int actionMasked = ev.getActionMasked() & MotionEvent.ACTION_MASK;
        if (actionMasked == MotionEvent.ACTION_MOVE && !mIsScroll) {
            return true;
        }

        if (actionMasked == MotionEvent.ACTION_DOWN) {
            // 记录手指按下时的位置
            mPosition = pointToPosition((int) ev.getX(), (int) ev.getY());
            return super.dispatchTouchEvent(ev);
        }
        // 手指抬起时
        if (actionMasked == MotionEvent.ACTION_UP
                || actionMasked == MotionEvent.ACTION_CANCEL) {
            // 手指按下与抬起都在同一个视图内,交给父控件处理,这是一个点击事件
            if (pointToPosition((int) ev.getX(), (int) ev.getY()) == mPosition) {
                super.dispatchTouchEvent(ev);
            } else {
                // 如果手指已经移出按下时的Item,说明是滚动行为,清理Item pressed状态, 点击事件都能通过触摸后移动来取消这个事件
                setPressed(false);
                invalidate();
                return true;
            }
        }
        return super.dispatchTouchEvent(ev);
    }
}

> 多级列表ExpandableListView

Android中多级列表可以使用ExpandableListView和SimpleExpandableListAdapter配合来实现。

这篇关于RecyclerView(局部刷新) 和 ListView(优化)的区别,ExpandableListView,ListView禁止上下滚动的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/417072

相关文章

Java中ArrayList和LinkedList有什么区别举例详解

《Java中ArrayList和LinkedList有什么区别举例详解》:本文主要介绍Java中ArrayList和LinkedList区别的相关资料,包括数据结构特性、核心操作性能、内存与GC影... 目录一、底层数据结构二、核心操作性能对比三、内存与 GC 影响四、扩容机制五、线程安全与并发方案六、工程

Deepseek使用指南与提问优化策略方式

《Deepseek使用指南与提问优化策略方式》本文介绍了DeepSeek语义搜索引擎的核心功能、集成方法及优化提问策略,通过自然语言处理和机器学习提供精准搜索结果,适用于智能客服、知识库检索等领域... 目录序言1. DeepSeek 概述2. DeepSeek 的集成与使用2.1 DeepSeek API

Tomcat高效部署与性能优化方式

《Tomcat高效部署与性能优化方式》本文介绍了如何高效部署Tomcat并进行性能优化,以确保Web应用的稳定运行和高效响应,高效部署包括环境准备、安装Tomcat、配置Tomcat、部署应用和启动T... 目录Tomcat高效部署与性能优化一、引言二、Tomcat高效部署三、Tomcat性能优化总结Tom

java中不同版本JSONObject区别小结

《java中不同版本JSONObject区别小结》本文主要介绍了java中不同版本JSONObject区别小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们... 目录1. FastjsON2. Jackson3. Gson4. org.json6. 总结在Jav

数据库使用之union、union all、各种join的用法区别解析

《数据库使用之union、unionall、各种join的用法区别解析》:本文主要介绍SQL中的Union和UnionAll的区别,包括去重与否以及使用时的注意事项,还详细解释了Join关键字,... 目录一、Union 和Union All1、区别:2、注意点:3、具体举例二、Join关键字的区别&php

解读Redis秒杀优化方案(阻塞队列+基于Stream流的消息队列)

《解读Redis秒杀优化方案(阻塞队列+基于Stream流的消息队列)》该文章介绍了使用Redis的阻塞队列和Stream流的消息队列来优化秒杀系统的方案,通过将秒杀流程拆分为两条流水线,使用Redi... 目录Redis秒杀优化方案(阻塞队列+Stream流的消息队列)什么是消息队列?消费者组的工作方式每

java中的HashSet与 == 和 equals的区别示例解析

《java中的HashSet与==和equals的区别示例解析》HashSet是Java中基于哈希表实现的集合类,特点包括:元素唯一、无序和可包含null,本文给大家介绍java中的HashSe... 目录什么是HashSetHashSet 的主要特点是HashSet 的常用方法hasSet存储为啥是无序的

Oracle查询优化之高效实现仅查询前10条记录的方法与实践

《Oracle查询优化之高效实现仅查询前10条记录的方法与实践》:本文主要介绍Oracle查询优化之高效实现仅查询前10条记录的相关资料,包括使用ROWNUM、ROW_NUMBER()函数、FET... 目录1. 使用 ROWNUM 查询2. 使用 ROW_NUMBER() 函数3. 使用 FETCH FI

C#使用HttpClient进行Post请求出现超时问题的解决及优化

《C#使用HttpClient进行Post请求出现超时问题的解决及优化》最近我的控制台程序发现有时候总是出现请求超时等问题,通常好几分钟最多只有3-4个请求,在使用apipost发现并发10个5分钟也... 目录优化结论单例HttpClient连接池耗尽和并发并发异步最终优化后优化结论我直接上优化结论吧,

Java内存泄漏问题的排查、优化与最佳实践

《Java内存泄漏问题的排查、优化与最佳实践》在Java开发中,内存泄漏是一个常见且令人头疼的问题,内存泄漏指的是程序在运行过程中,已经不再使用的对象没有被及时释放,从而导致内存占用不断增加,最终... 目录引言1. 什么是内存泄漏?常见的内存泄漏情况2. 如何排查 Java 中的内存泄漏?2.1 使用 J