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配合来实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值