RecycleView 在調(diào)用Adapter.notifyDataSetChanged()的時(shí)候往往整個(gè)屏幕會(huì)閃爍,特別是有Picasso這種異步加載圖片框架的時(shí)候特別明顯。這里有幾種方法可以解決,個(gè)人比較推薦第三種方式:通過(guò)更改ViewHolder 來(lái)更新,雖然感覺(jué)上會(huì)麻煩些,但是體驗(yàn)效果特別特別好!
1.只更新1個(gè)item:
Adapter有許多更新方式 除了notifyDataSetChange還有很多,有時(shí)間大家可以看看,我們這里直接調(diào)用
Adapter.notifyItemChanged(int Position),
這種方式可以只刷新你要更新的數(shù)據(jù),其他的數(shù)據(jù)是不會(huì)更新的,其他的也就不閃了。
2.取消動(dòng)畫
上述第一個(gè)方法有個(gè)弊端,就是你要更新的那個(gè)item會(huì)有刷新閃爍,其實(shí)我也看了一些人的資料,然后去項(xiàng)目里面看源碼,RecycleView用的動(dòng)畫實(shí)體類是DefaultItemAnimator 這個(gè)類繼承的父類是SimpleItemAnimator,然后這個(gè)類的父類是在RecycleView里面的抽象類ItemAnimator,其中定義如下:
private long mAddDuration = 120;
private long mRemoveDuration = 120;
private long mMoveDuration = 250;
private long mChangeDuration = 250;
看到了吧,動(dòng)畫也是要有執(zhí)行時(shí)間的,總結(jié)來(lái)說(shuō)就是更改recycleView的動(dòng)畫,減少動(dòng)畫時(shí)間可以減少item的閃爍。
設(shè)置動(dòng)畫大致方法:
recyclerView.getItemAnimator().setChangeDuration(0); //設(shè)置更新動(dòng)畫duration為0,其他的你也可以設(shè)置。
((DefaultItemAnimator)mRecyclerView.getItemAnimator()).setSupportsChangeAnimations(false);//取消動(dòng)畫
或者你愿意的話自定義一個(gè)動(dòng)畫類,這個(gè)類必須繼承自SimpleAnimator,換個(gè)說(shuō)法就是,改一下DefalutAnimator 中的動(dòng)畫效果
因?yàn)镽ecycleView 的動(dòng)畫實(shí)體類就是它。不講太細(xì),我們的目標(biāo)是頁(yè)面不閃爍。
3.通過(guò)更改ViewHolder 來(lái)更新
我覺(jué)得更新數(shù)據(jù)是最輕松的,通過(guò)下面那個(gè)方法獲取ViewHolder,有了viewHolder,有了數(shù)據(jù)你啥不能更新的, 想更新什么就更新什么,而且可以避免因?yàn)橹匦翺nBinderView 導(dǎo)致的資源浪費(fèi)。使用這個(gè)的時(shí)候同時(shí)要記得更新adapter 中的數(shù)據(jù)集,避免數(shù)據(jù)不一致。
(myAdapter.CustomViewHolder) mRecyclerView.findViewHolderForAdapterPosition(i);//獲取ViewHolder
這好歸好,但是這里往往有些問(wèn)題,一般adapter 里面的ViewHolder 很少拿到 adapter 外部去,都是在Adapter里面更新,這樣ViewHolder 的內(nèi)容可以隨便變化,只要數(shù)據(jù)是對(duì)的就好了,但是拿到外部去了之后,以后你想改代碼要麻煩死了雖然我是這樣解決的
mAdapter.updateView(holder,n);
但是也是有殘留的,除非你把RecyclerView的實(shí)體也放到adapter 里面去了,就當(dāng)我沒(méi)說(shuō)這話。