Android列表動(dòng)圖展示的實(shí)現(xiàn)策略
前言
在最近的時(shí)間里,短視頻流行了起來(lái),隨著這股潮流,一種動(dòng)圖封面的設(shè)計(jì)也被很多短視頻app采用:

某音
而在app中,動(dòng)圖的展示是比較消耗性能的操作,對(duì)于這種一頁(yè)非常多的動(dòng)圖在展示時(shí)需要做對(duì)應(yīng)的處理,今天我結(jié)合自己在項(xiàng)目中處理的經(jīng)驗(yàn)分享一下多動(dòng)圖的處理策略。
圖片加載框架選擇
對(duì)于動(dòng)圖的加載,尤其是webp格式的動(dòng)圖,F(xiàn)resco真是不二的選擇,而且fresco本身對(duì)內(nèi)存的處理也很棒,本文是基于Fresco 1.0.10版本,如果使用低版本Fresco出現(xiàn)無(wú)解的問(wèn)題時(shí),不妨可以試著升級(jí)Fresco版本。
圖片展示的策略
只在當(dāng)前頁(yè)展示
我們知道,動(dòng)圖是由一幀一幀的靜圖組成的,通常來(lái)說(shuō)我們需要這個(gè)動(dòng)圖一直播放,也就是說(shuō)動(dòng)圖從加載完成之后會(huì)不停的渲染每一幀,拿某音舉例:

首頁(yè)
假設(shè)下面的“首頁(yè)”“、”關(guān)注”、“消息”、“我”4個(gè)tab都有動(dòng)圖,當(dāng)我們點(diǎn)擊其他頁(yè)面時(shí),當(dāng)前頁(yè)被隱藏,而根據(jù)Fresco的官方文檔Fresco中文官方文檔通常只有當(dāng)SimpleDrawView被移出屏幕才會(huì)停止播放動(dòng)畫(huà)(我在測(cè)試中發(fā)現(xiàn)通常Activity生命周期級(jí)別的也會(huì)觸發(fā)),所以當(dāng)tab頁(yè)隱藏時(shí)動(dòng)圖依舊在被渲染,所以我們需要控制動(dòng)圖的停止和播放,只有當(dāng)前頁(yè)展示時(shí),才播放動(dòng)圖:
Animatable animatable = mSimpleDraweeView.getController().getAnimatable();
if (animatable != null) {
animatable.start();
// later
animatable.stop();
}
只在可見(jiàn)區(qū)域展示
當(dāng)我們做列表動(dòng)圖的時(shí)候,無(wú)論控件是listview還是recyclerview,數(shù)據(jù)和item的綁定都會(huì)在屏幕外綁定,而此時(shí)站在性能優(yōu)化的角度上,是不需要渲染動(dòng)圖的;當(dāng)動(dòng)圖滑動(dòng)在列表邊界的時(shí)候,是不是說(shuō)明用戶的焦點(diǎn)已經(jīng)不在這張圖上了,所以此時(shí)可以提前在動(dòng)圖滑出屏幕外之前停止動(dòng)圖播放(在項(xiàng)目中我與產(chǎn)品商定動(dòng)圖播放和停止的邊界值定為圖片的1/2,也就是說(shuō)圖片滑入屏幕自身長(zhǎng)度1/2的時(shí)候播放動(dòng)圖,滑出屏幕自身長(zhǎng)度1/2的時(shí)候停止播放);當(dāng)快速滑動(dòng)的時(shí)候也應(yīng)當(dāng)停止動(dòng)圖渲染(平時(shí)加載靜圖可能不需要在意,但是在android老手機(jī)上加載很多動(dòng)圖會(huì)使得cpu和內(nèi)存大幅度浮動(dòng))。
也就是說(shuō)當(dāng)列表在做數(shù)據(jù)綁定的時(shí)候我們應(yīng)當(dāng)先去加載圖片但并不渲染動(dòng)圖,動(dòng)圖播放和停止唯一的判斷標(biāo)準(zhǔn)是滑入滑出屏幕的長(zhǎng)度,如果是快速滑動(dòng)則無(wú)視第二個(gè)規(guī)則直接停止所有的動(dòng)圖。
上面的第二、第三個(gè)處理會(huì)有些許的代碼量,而且重點(diǎn)是時(shí)機(jī)的判斷不是動(dòng)圖的處理,這里著重講策略,代碼就略過(guò)了。對(duì)于第一個(gè)處理,F(xiàn)resco本身是支持的:
DraweeController controller = Fresco.newDraweeControllerBuilder()
.setUri(uri)
.setAutoPlayAnimations(false)
. // 其他設(shè)置(如果有的話)
.build();
setAutoPlayAnimations即表示是否在加載完成之后立即播放動(dòng)圖,這里設(shè)置為false即可,滑入播放調(diào)用上一張圖的方法就行了??墒沁€有一種情況,動(dòng)圖在我們滑入的時(shí)候還沒(méi)有加載完成,那么我們就可以設(shè)置一個(gè)標(biāo)示來(lái)表示是否播放,因?yàn)镾impleDrwaView是可以拿到動(dòng)圖加載的回調(diào)的:
ControllerListener controllerListener = new BaseControllerListener<ImageInfo>() {
@Override
public void onFinalImageSet(
String id,
@Nullable ImageInfo imageInfo,
@Nullable Animatable anim) {
if (anim != null && tag == BEGAIN) {
// 其他控制邏輯
anim.start();
}
}
};
滑入屏幕時(shí),就把tag 置為BEGAIN,滑出再置空就行了,并且這里我們不用擔(dān)心重復(fù)播放和停止的問(wèn)題,這里的anim對(duì)象其實(shí)是AnimatedDrawble2對(duì)象,而該對(duì)象在start和stop的時(shí)候都對(duì)狀態(tài)進(jìn)行了判斷。
圖片的規(guī)格尺寸
規(guī)格
相較于傳統(tǒng)的gif,同質(zhì)量的webp體積更小,更能節(jié)省存儲(chǔ)空間,但是在解碼上webp更為耗時(shí),所以能用webp盡量用webp,實(shí)在還是卡再考慮用gif。
幀率
目前調(diào)研發(fā)現(xiàn)的動(dòng)圖幀率一般是10幀或者20幀,幀率不要太高了,不然會(huì)加大cpu的占用率,其實(shí)如果Fresco的使用方式?jīng)]出問(wèn)題,內(nèi)存的問(wèn)題Fresco已經(jīng)幫你搞定了,其他的優(yōu)化主要是針對(duì)cpu占用率優(yōu)化的。在項(xiàng)目中我們加載的動(dòng)圖最后采用的是20幀(模仿騰訊謀產(chǎn)品的策略,最好控制在10幀其實(shí),這款騰訊的產(chǎn)品在一頁(yè)上展示的動(dòng)圖明顯比其他同類型產(chǎn)品展示的數(shù)量少)。
大小
動(dòng)圖的大小也會(huì)影響解碼耗時(shí),在手機(jī)端可以使用小圖,在項(xiàng)目中,我們手機(jī)端的動(dòng)圖最多在200kb左右。
在實(shí)際的開(kāi)發(fā)中,可能因?yàn)闃I(yè)務(wù)的關(guān)系,上述的策略不能保證全部都做到,這里時(shí)候就得根據(jù)業(yè)務(wù)形態(tài)做對(duì)應(yīng)的取舍,這里可能是一個(gè)長(zhǎng)久優(yōu)化的過(guò)程,畢竟這種新的動(dòng)圖封面設(shè)計(jì)以前都沒(méi)有遇到過(guò)。
總結(jié):
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
- android listview實(shí)現(xiàn)新聞列表展示效果
- Android RecyclerView實(shí)現(xiàn)數(shù)據(jù)列表展示效果
- android 支持的語(yǔ)言列表(匯總)
- Android通過(guò)LIstView顯示文件列表的兩種方法介紹
- Android uses-permission權(quán)限列表中文注釋版
- Android ExpandableListView展開(kāi)列表控件使用實(shí)例
- Android 實(shí)現(xiàn)WebView點(diǎn)擊圖片查看大圖列表及圖片保存功能
- Android 仿抖音的評(píng)論列表的UI和效果的實(shí)現(xiàn)代碼
相關(guān)文章
在Android項(xiàng)目中使用AspectJ的詳細(xì)攻詻
AspectJ是實(shí)現(xiàn)AOP的其中一款框架,內(nèi)部通過(guò)處理字節(jié)碼實(shí)現(xiàn)代碼注入,文章給大家提到AspectJ基礎(chǔ)語(yǔ)法和集成AspectJ的方式,對(duì)AspectJ在android中使用教程感興趣的朋友跟隨小編一起看看吧2021-06-06
記錄Android studio JNI開(kāi)發(fā)的三種方式(推薦)
JNI (Java Native Interface)是一套編程接口,用來(lái)實(shí)現(xiàn)Java代碼和其他語(yǔ)言(c、C++或匯編)進(jìn)行交互。下面通過(guò)本文給大家講解Android studio JNI開(kāi)發(fā)的三種方式,需要的朋友參考下吧2017-12-12
Android RecyclerView 實(shí)現(xiàn)快速滾動(dòng)的示例代碼
本篇文章主要介紹了Android RecyclerView 實(shí)現(xiàn)快速滾動(dòng)的示例代碼,具有一定的參考價(jià)值,有興趣的可以了解一下2017-09-09
Android開(kāi)發(fā) 旋轉(zhuǎn)屏幕導(dǎo)致Activity重建解決方法
Android開(kāi)發(fā)文檔上專門有一小節(jié)解釋這個(gè)問(wèn)題。簡(jiǎn)單來(lái)說(shuō),Activity是負(fù)責(zé)與用戶交互的最主要機(jī)制,接下來(lái)為您詳細(xì)介紹2012-11-11
Android系列之Intent傳遞對(duì)象的幾種實(shí)例方法
Android系列之Intent傳遞對(duì)象的幾種實(shí)例方法,需要的朋友可以參考一下2013-05-05
Android實(shí)現(xiàn)app分享文件到微信功能
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)app分享文件到微信功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-05-05

