Android Fresco圖片加載優(yōu)化的方案
優(yōu)化背景
一般情況下,F(xiàn)resco圖片加載需使用SimpleDraweeView,這個控件并不能自動根據(jù)自身的尺寸按需加載圖片,即一個 N×N 的UI控件,背后加載的實際圖片可能是 2N×2N。這就導(dǎo)致了實際應(yīng)用運行過程中的內(nèi)存使用效率不高,需要針對其進行內(nèi)存優(yōu)化。

在一些入門級硬件設(shè)備上,表現(xiàn)得尤為明顯,隨著程序的運行時間的增長,OOM的風(fēng)險也不斷加大。
Fresco版本:1.13.0
數(shù)據(jù)記錄
聲明控件大小為 480×270
<com.facebook.drawee.view.SimpleDraweeView android:id="@+id/simple_drawee_view" android:layout_width="480dp" android:layout_height="270dp" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" />
加載圖片代碼,調(diào)用Fresco的setImageURI
val mImageUrl = "https://static.runoob.com/images/demo/demo4.jpg" val simple_drawee_view = findViewById<SimpleDraweeView>(R.id.simple_drawee_view) simple_drawee_view.setImageURI(mImageUrl)
運行后dump內(nèi)存如下,可以發(fā)現(xiàn)內(nèi)存中的圖片尺寸為1920×1080,即此時SimpleDraweeView會按照網(wǎng)絡(luò)上的原圖尺寸進行加載,內(nèi)存占用大小為 8294475Bytes = 7.91Mb。一張圖片占用近8Mb,在圖片顯示十分豐富的頁面場景中,圖片總內(nèi)存占用大小將特別美麗,萬一這個頁面又內(nèi)存泄漏了,那就更美麗了。

如果只加載 480×270 大小的圖片,內(nèi)存占用為 518475Bytes = 0.49Mb。相較于原來 1920×1080 尺寸,內(nèi)存減小了 94%!

優(yōu)化方案
Fresco提供了resize api,使得調(diào)用者在圖片解碼前可以修改內(nèi)存中圖片的大小,api大致如下
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri) .setResizeOptions(new ResizeOptions(width, height)) .build(); PipelineDraweeController controller = Fresco.newDraweeControllerBuilder() .setOldController(mDraweeView.getController()) .setImageRequest(request) .build(); mSimpleDraweeView.setController(controller);
注意這個方案在低版本中默認只支持jpg圖片,如需支持其它圖片格式,需在設(shè)置image pipeline時添加isDownSample配置。同時對于產(chǎn)生的圖片的尺寸,只能粗略地控制,圖片不能修改為確定的尺寸。
.setDownsampleEnabled(true)
這個方案有個顯著的缺點,那就是頁面適配性極差,需要配合View層的生命周期在確保能夠動態(tài)獲取到控件寬高的時機進行調(diào)用,對于一個成熟的項目工程,代碼改動量過大,優(yōu)化成本過高。 這里采用編寫SimpleDraweeView的子類進行優(yōu)化,利用向上轉(zhuǎn)型,盡可能的減小View層代碼的改動,只需要修改xml布局文件中的控件聲明即可。 方案架構(gòu)圖如下:

其中DesiredSimpleDraweeView為SimpleDraweeView的子類,在onWindowFocusChanged方法回調(diào)中可以明確獲知控件的具體寬高,之后再進行圖片加載操作。
public class DesiredSimpleDraweeView extends SimpleDraweeView {
Uri mUri;
Object mCallerContext;
public DesiredSimpleDraweeView(Context context) {
super(context);
}
@Override
public void setImageURI(Uri uri, Object callerContext) {
mUri = uri;
mCallerContext = callerContext;
}
private void setImageURI(int width, int height) {
try {
ImageRequest imageRequest = ImageRequestBuilder.newBuilderWithSource(mUri)
.setResizeOptions(new ResizeOptions(width, height))
.build();
DraweeController controller =
getControllerBuilder()
.setOldController(getController())
.setImageRequest(imageRequest)
.build();
setController(controller);
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
super.onWindowFocusChanged(hasWindowFocus);
if (hasWindowFocus) {
setImageURI(getWidth(), getHeight());
}
}
}
復(fù)寫setImageURI(Uri,Object)方法,暫存uri和callerContext,在onWindowFoucusChanged回調(diào)之后再根據(jù)控件寬高進行圖片的加載。 這樣,利用向上轉(zhuǎn)型,View層的代碼無需改動,xml文件中替換控件聲明后即可顯著提高內(nèi)存利用率。
注意事項
性能優(yōu)化是條永無止境的道路,沒有最牛的方案,只有最合適的方案。如果對于圖片加載尺寸想要精確控制,按需加載,Glide或許是更好的選擇。
以上就是Android Fresco圖片加載優(yōu)化的方案的詳細內(nèi)容,更多關(guān)于Android Fresco圖片加載優(yōu)化的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
android利用ContentResolver訪問者獲取手機短信信息
本篇文章主要介紹了android利用ContentResolver訪問者獲取手機短信信息,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-02-02
Android使用AlarmManager設(shè)置鬧鐘功能
這篇文章主要為大家詳細介紹了Android使用AlarmManager設(shè)置鬧鐘功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-09-09
Android使用ContentProvider初始化SDK庫方案小結(jié)
這篇文章主要介紹了Android使用ContentProvider初始化SDK庫方案總結(jié),本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-04-04
Android ViewPager的MVP架構(gòu)搭建過程
本文主要介紹了ViewPager在Android中的作用以及使用場景,如引導(dǎo)頁、圖片瀏覽器、新聞或文章內(nèi)容的多標(biāo)簽頁等,同時,還詳細闡述了如何通過MVP架構(gòu)來搭建ViewPager,將視圖和邏輯進行解耦,提高代碼的可測試性、可復(fù)用性,使代碼結(jié)構(gòu)更清晰且易于擴展功能2024-10-10
安卓監(jiān)聽屏幕的橫豎翻轉(zhuǎn)實現(xiàn)方法
這篇文章主要介紹了安卓監(jiān)聽屏幕的橫豎翻轉(zhuǎn)實現(xiàn)方法,有需要的朋友可以參考一下2013-12-12

