使用Picasso加载图片的内存优化实践

原地址:http://blog.csdn.net/ashqal/article/details/48005833


0 说明

现在Android开源库中有许多图片加载框架,本文以picasso为例,总结下开发过程中的一些优化经验,使用的picasso版本如下

<code class="hljs bash has-numbering">compile <span class="hljs-string">'com.squareup.picasso:picasso:2.5.2'</span></code><ul style="display: block;" class="pre-numbering"><li>1</li></ul>

1 图片裁剪

在列表页尽量使用裁剪后的图片,在查看大图模式下才加载完整的图片。

图片裁剪示例

<code class="language-java hljs  has-numbering">Picasso.with( imageView.getContext() )
.load(url)
.resize(dp2px(<span class="hljs-number">250</span>),dp2px(<span class="hljs-number">250</span>))
.centerCrop()
.into(imageView);</code><ul style="display: block;" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul>

picasso默认情况下会使用全局的ApplicationContext,即开发者传进去Activity,picasso也会通过activity获取ApplicationContext。

2 查看大图放弃memory cache

Picasso默认会使用设备的15%的内存作为内存图片缓存,且现有的api无法清空内存缓存。我们可以在查看大图时放弃使用内存缓存,图片从网络下载完成后会缓存到磁盘中,加载会从磁盘中加载,这样可以加速内存的回收。

<code class="language-java hljs  has-numbering">Picasso.with(getApplication())
.load(mURL)
.memoryPolicy(NO_CACHE, NO_STORE)
.into(imageView);</code><ul style="display: block;" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li></ul>

其中memoryPolicy的NO_CACHE是指图片加载时放弃在内存缓存中查找,NO_STORE是指图片加载完不缓存在内存中。

3 RecyclableImageView

重写ImageView的onDetachedFromWindow方法,在它从屏幕中消失时回调,去掉drawable引用,能加快内存的回收。

<code class="language-java hljs  has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RecyclerImageView</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ImageView</span>
{</span> 
    ...

    <span class="hljs-annotation">@Override</span>    
    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onDetachedFromWindow</span>() {
        <span class="hljs-keyword">super</span>.onDetachedFromWindow();
        setImageDrawable(<span class="hljs-keyword">null</span>);   
    }
}</code><ul style="display: block;" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li></ul>

实验环境:加载大图不使用内存缓存。
实验场景:从图片列表页切换到详情页看大图,然后返回,不停重复。

普通ImageView

RecyclableImageView

可以看到使用了RecyclableImageView的实验在切换过程中产生的内存谷值明显优于ImageView,说明drawable更容易被回收。

4 新进程中查看大图

列表页的内存已经非常稳定,但是查看大图时,大图往往占用了20+m内存,加上现有进程中的内存,非常容易oom,在新进程中打开Activity成为比较取巧的避免oom的方式。

<code class="language-xml hljs  has-numbering"><span class="hljs-tag"><<span class="hljs-title">activity</span> <span class="hljs-attribute">android:name</span>=<span class="hljs-value">".DetailActivity"</span> <span class="hljs-attribute">android:process</span>=<span class="hljs-value">":picture"</span>/></span></code><ul style="display: block;" class="pre-numbering"><li>1</li></ul>

只要在AndroidManifest.xml中定义Activity时加入process属性,即可在新进程中打开此Activity。由此,picasso也将在新进程中创建基于新ApplicationContext的单例。

5 列表页滑动优化

picasso可以对多个加载请求设置相同的tag,即

<code class="language-java hljs  has-numbering">Object tag = <span class="hljs-keyword">new</span> Object();</code><ul style="display: block;" class="pre-numbering"><li>1</li></ul>
<code class="language-java hljs  has-numbering">Picasso.with( imageView.getContext() )
.load(url)
.resize(dp2px(<span class="hljs-number">250</span>),dp2px(<span class="hljs-number">250</span>))
.centerCrop()
.tag(tag)
.into(imageView);</code><ul style="display: block;" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li></ul>

例如在RecyclerView滑动时监听,处理不同的表现:

<code class="language-java hljs  has-numbering">mRecyclerView.addOnScrollListener(<span class="hljs-keyword">new</span> RecyclerView.OnScrollListener(){
    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onScrollStateChanged</span>(RecyclerView recyclerView, <span class="hljs-keyword">int</span> newState)
    {
        <span class="hljs-keyword">if</span> (newState == RecyclerView.SCROLL_STATE_IDLE)
        {
            Picasso.with(context).resumeTag(tag);
        }
        <span class="hljs-keyword">else</span>
        {
            Picasso.with(context).pauseTag(tag);
        }
    }
});</code><ul style="display: block;" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li></ul>

6 RGB_565

对于不透明的图片可以使用RGB_565来优化内存。

<code class="language-java hljs  has-numbering">Picasso.with( imageView.getContext() )
.load(url)
.config(Bitmap.Config.RGB_565)
.into(imageView);</code><ul style="display: block;" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li></ul>

默认情况下,Android使用ARGB_8888

<code class="hljs cs has-numbering">Android中有四种,分别是:
ALPHA_8:每个像素占用<span class="hljs-number">1</span><span class="hljs-keyword">byte</span>内存
ARGB_4444:每个像素占用<span class="hljs-number">2</span><span class="hljs-keyword">byte</span>内存
ARGB_8888:每个像素占用<span class="hljs-number">4</span><span class="hljs-keyword">byte</span>内存
RGB_565:每个像素占用<span class="hljs-number">2</span><span class="hljs-keyword">byte</span>内存</code><ul style="display: block;" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul>

RGB_565呈现结果与ARGB_8888接近,内存对比如下图

默认ARGB_8888,列表滑动时平均内存10m

RGB_565,列表滑动时,平均7M

7 reference

Picasso and Context
JakeWharton的避免OOM建议
Clear Cache memory of Picasso

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值