摘要:前言安卓開發(fā)者都知道,比要靈活的多,但不可否認(rèn)的里面的坑也同樣埋了不少人。下面讓我們看看騰訊開發(fā)工程師用實例講解自己踩坑時的解決方案和心路歷程。
前言
安卓開發(fā)者都知道,RecyclerView比ListView要靈活的多,但不可否認(rèn)的里面的坑也同樣埋了不少人。下面讓我們看看騰訊開發(fā)工程師用實例講解自己踩坑時的解決方案和心路歷程。
話說有圖有真相,首先來對比一下局部刷新前后的效果:
優(yōu)化之前的效果:
優(yōu)化之后的效果:
可以看到,優(yōu)化之后,列表中的這張大圖不在有一閃一閃亮晶晶的效果了!
那么,這是如何做到的呢?這是本文的重點(diǎn),本文的大綱主要包括:
?一、為什么會閃一下?分析為什么會閃一下
對分析的可能造成閃動的問題進(jìn)行解決
驗證是否解決
我們的需求是大家已經(jīng)看到了,點(diǎn)擊打分,彈出一個對話框,點(diǎn)擊一個分?jǐn)?shù),這時候,通過一些列復(fù)雜的轉(zhuǎn)換(當(dāng)然不是本文的論述的重點(diǎn)),這時候到了要更新列表項了,如是很自然,我們會這么做:
因為,操作的那個列表項你是知道他的position,所以你可以這么做,(當(dāng)然,我之前是直接notifyDataSetChanged的,這個會照成所以不不要的item也會刷新)然而,閃動還是出現(xiàn)了,那么我開始懷疑:
?二、帶著思考,就去嘗試吧!流傳甚為廣泛的一種說法,imageView的寬高不固定導(dǎo)致的(wrap_content)?
這個是RecyclerView自帶的更新動畫效果導(dǎo)致的?
這個是因為圖片加載框架(glide 的 animte)的動畫效果導(dǎo)致的?
getView中(RecyclerView中是onBindViewHolder)加載圖片的時候,設(shè)置一個tag,當(dāng)發(fā)現(xiàn)這個imageView的tag和之前的tag一致時就不加載
1、對于第一種,我的做法是自己寫了一個自定義的imageView,重寫omMeasure方法,如下:
因為我們的這個列表項中的圖片是(高=寬)的,因此,我才這么寫,這樣寫也有一個好處,不用在onBindViewHolder中去動態(tài)的計算出高度,然后在已layoutParm的方式設(shè)置給imageView,相信不少小伙伴都做過了吧!
然而,遺憾的是,他并沒有解決閃一下的問題!此時這個閃動的原因顯然不在這里,但是這里做的,可以保留下來。
2、對于第二種說法,我參考了這里http://stackoverflow.com/ques...
的做法:
以及也嘗試了這種
然而,那種漸變的閃動消失了,但是,取而代之的是一種更加不可接受的閃動,這里就不用gif展示了,因此原因也并不在此處。
3、對于對三種說法,我也去嘗試了一下將glide加載改為:
然而得到的依然是一個失望的結(jié)果,依然沒有解決閃動的問題,原因也不在此處。
4、那么,就剩下最后一個猜測了,那么會不會是它呢?那就試試吧,于是代碼改為:
這里的做法其實就是設(shè)置Tag,那么是騾子是馬,拉出來溜溜吧,結(jié)果更加令人發(fā)指,如圖:
好吧,此時已經(jīng)有點(diǎn)崩潰了,顯然這個也不是我要的結(jié)果,那么此時是否應(yīng)該在靜下來想一想,自己對于可能的幾種原因做過的一些對策,是否有哪里遺漏了。經(jīng)過思考,發(fā)現(xiàn)并沒有!!那么一定是還有其他的原因,沒有考慮到!
還是去翻一翻RecyclerView的api吧,我注意到了這個api:
可以看到這里有一個payload的參數(shù),use null to identify a "full" update這是說如果傳null就是全部更新,回過頭去看一看我們之前的調(diào)用方式:
看一下源碼,發(fā)現(xiàn)
實際上,payload這個參數(shù)就是傳的null,那也就是說如果傳一個不為null的參數(shù),就可以對列表項中的具體控件更新了?
http://stackoverflow.com/ques...
我了解到這個方法的使用方式是這樣的:
然來,onBindViewHolder有這么一個重載方式,如是我也這么做了,在下面這個重載中,去更新我想更新的控件:
然后,更新的方式變成了這種:
是騾子是馬,那就在遛一遛吧!
然而,依然是會閃一下!!!這這么會!!!還是調(diào)試一下吧,新重載onBindViewHolder方法有沒有被執(zhí)行,一更代碼,發(fā)現(xiàn)果然沒有被執(zhí)行!那么,究竟是什么鬼?去網(wǎng)上查了一下,有人給出了一個解決辦法:
http://stackoverflow.com/ques...
需要重寫這個動畫,讓永遠(yuǎn)返回true,已達(dá)到newHolder和olderHolder是同一個,然而,這真的就是我的救命稻草嗎?
那么,是騾子是馬,拉出來溜溜吧,然而,并不是馬!!進(jìn)源碼看一看
發(fā)現(xiàn)其實只要我們傳入的payload不為空,那么返回的就是true?重寫有意義嗎?顯然,我重載的onBindViewHolder方法并沒有執(zhí)行的原因顯然不是這個。
那么,到底,到底問題出在何處?會不會是XrecyclerView的問題?根據(jù)調(diào)用棧,我看到第一個onBindViewHolder被執(zhí)行了,往上面跟,發(fā)現(xiàn)XrecyclerView的實現(xiàn)果然存在問題!
如圖,作者僅僅只實現(xiàn)了,不帶payload的方法,最后adapter調(diào)用的只有不帶paylaod的方法!所以,重寫一個吧!
最后!終于達(dá)到了想要的效果了,經(jīng)過這次爬坑,選擇一個開源的框架真滴是需要慎重再慎重。
總結(jié)實際上RecyclerView做局部刷新是非常容易的,其實就是使用好帶payload參數(shù)的這個notifyItemRangeChanged方法,以及override帶payload的這個onBindViewHolder方法,在onBindViewHolder中去刷新你想更新的控件即可,并非是網(wǎng)上傳聞的那些原因,當(dāng)然此處爬坑時間之長,也可能更選用開源控件不當(dāng)有關(guān),所以,選擇開源控件,要謹(jǐn)慎再謹(jǐn)慎!
原文鏈接:http://wetest.qq.com/lab/view...
閱讀更多
kotlin學(xué)習(xí)筆記-異常好玩的list集合總結(jié)
一份完整的Android Studio搭建Flutter教程
NDK項目實戰(zhàn)—高仿360手機(jī)助手之卸載監(jiān)聽
(Android)面試題級答案(精選版)
相信自己,沒有做不到的,只有想不到的在這里獲得的不僅僅是技術(shù)!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/71634.html
閱讀 2609·2021-09-28 09:35
閱讀 3262·2021-09-03 10:28
閱讀 2905·2019-08-30 15:43
閱讀 1477·2019-08-30 14:04
閱讀 1801·2019-08-29 17:02
閱讀 1812·2019-08-26 13:59
閱讀 692·2019-08-26 11:51
閱讀 3251·2019-08-23 17:16