0 說明
現(xiàn)在Android開源庫中有許多圖片加載框架,本文以picasso為例,總結(jié)下開發(fā)過程中的一些優(yōu)化經(jīng)驗(yàn)荚恶,使用的picasso版本如下
compile 'com.squareup.picasso:picasso:2.5.2'
1 圖片裁剪
在列表頁盡量使用裁剪后的圖片哩牍,在查看大圖模式下才加載完整的圖片。
圖片裁剪示例
Picasso.with( imageView.getContext() )
.load(url)
.resize(dp2px(250),dp2px(250))
.centerCrop()
.into(imageView);
picasso默認(rèn)情況下會使用全局的ApplicationContext儡率,即開發(fā)者傳進(jìn)去Activity,picasso也會通過activity獲取ApplicationContext以清。
2 查看大圖放棄memory cache
Picasso默認(rèn)會使用設(shè)備的15%的內(nèi)存作為內(nèi)存圖片緩存喉悴,且現(xiàn)有的api無法清空內(nèi)存緩存。我們可以在查看大圖時(shí)放棄使用內(nèi)存緩存玖媚,圖片從網(wǎng)絡(luò)下載完成后會緩存到磁盤中箕肃,加載會從磁盤中加載,這樣可以加速內(nèi)存的回收今魔。
Picasso.with(getApplication())
.load(mURL)
.memoryPolicy(NO_CACHE, NO_STORE)
.into(imageView);
其中memoryPolicy的NO_CACHE是指圖片加載時(shí)放棄在內(nèi)存緩存中查找勺像,NO_STORE是指圖片加載完不緩存在內(nèi)存中。
3 RecyclableImageView
重寫ImageView的onDetachedFromWindow方法错森,在它從屏幕中消失時(shí)回調(diào)吟宦,去掉drawable引用,能加快內(nèi)存的回收涩维。
public class RecyclerImageView extends ImageView
{
...
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
setImageDrawable(null);
}
}
實(shí)驗(yàn)環(huán)境:加載大圖不使用內(nèi)存緩存殃姓。
實(shí)驗(yàn)場景:從圖片列表頁切換到詳情頁看大圖袁波,然后返回,不停重復(fù)蜗侈。
可以看到使用了RecyclableImageView的實(shí)驗(yàn)在切換過程中產(chǎn)生的內(nèi)存谷值明顯優(yōu)于ImageView篷牌,說明drawable更容易被回收。
4 新進(jìn)程中查看大圖
列表頁的內(nèi)存已經(jīng)非常穩(wěn)定踏幻,但是查看大圖時(shí)枷颊,大圖往往占用了20+m內(nèi)存,加上現(xiàn)有進(jìn)程中的內(nèi)存该面,非常容易o(hù)om夭苗,在新進(jìn)程中打開Activity成為比較取巧的避免oom的方式。
<activity android:name=".DetailActivity" android:process=":picture"/>
只要在AndroidManifest.xml中定義Activity時(shí)加入process屬性隔缀,即可在新進(jìn)程中打開此Activity题造。由此,picasso也將在新進(jìn)程中創(chuàng)建基于新ApplicationContext的單例猾瘸。
5 列表頁滑動優(yōu)化
picasso可以對多個(gè)加載請求設(shè)置相同的tag界赔,即
Object tag = new Object();
Picasso.with( imageView.getContext() )
.load(url)
.resize(dp2px(250),dp2px(250))
.centerCrop()
.tag(tag)
.into(imageView);
例如在RecyclerView滑動時(shí)監(jiān)聽,處理不同的表現(xiàn):
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener(){
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState)
{
if (newState == RecyclerView.SCROLL_STATE_IDLE)
{
Picasso.with(context).resumeTag(tag);
}
else
{
Picasso.with(context).pauseTag(tag);
}
}
});
6 RGB_565
對于不透明的圖片可以使用RGB_565來優(yōu)化內(nèi)存须妻。
Picasso.with( imageView.getContext() )
.load(url)
.config(Bitmap.Config.RGB_565)
.into(imageView);
默認(rèn)情況下仔蝌,Android使用ARGB_8888
Android中有四種泛领,分別是:
ALPHA_8:每個(gè)像素占用1byte內(nèi)存
ARGB_4444:每個(gè)像素占用2byte內(nèi)存
ARGB_8888:每個(gè)像素占用4byte內(nèi)存
RGB_565:每個(gè)像素占用2byte內(nèi)存
RGB_565呈現(xiàn)結(jié)果與ARGB_8888接近荒吏,內(nèi)存對比如下圖
7 reference
Picasso and Context
JakeWharton的避免OOM建議
Clear Cache memory of Picasso