Andorid Volley框架加载图片OOM问题分析

原创 2015年01月06日 14:53:57

一、Volley框架简介

在这之前,我们在程序中需要和网络通信的时候,大体使用的东西莫过于AsyncTaskLoader,HttpURLConnection,AsyncTask,HTTPClient(Apache)等,Google 在2013年的I/O大会 上,发布了Volley。Volley是Android平台上的网络通信库,能使网络通信更快,更简单,更健壮。

Volley提供了JsonObjectRequest、JsonArrayRequestStringRequest等Request形式

JsonObjectRequest:返回JSON对象

JsonArrayRequest:返回JsonArray。

StringRequest:返回String,这样可以自己处理数据,更加灵活

另外可以继承自定义Request。

二、VOlley引起的OOM项目中用到Volley下载网络图片,在回调中获取到bitmap做相应地操作。

       ImageRequest imageRequest = new ImageRequest(url+"--"+ bmWidth+"x"+bmWidth+".png",                new Response.Listener<Bitmap>() {                    @Override                    public void onResponse(Bitmap response) {                        initViewWithBitmap(response);                    }                }, 0, 0, Bitmap.Config.RGB_565, getImageError);        mQueue.add(imageRequest);

起初发现在这个界面操作偶先强关问题,抓到log看下是 outofmemory引起的。

由于该界面用到bitmap的地方比较多,所以在onDestoy()方法中手动释放bitmap。

用内存查看器观察该界面的内存情况,发现每次进入退出后,内存并没有完全释放,大概每次都来6M左右

三、问题分析

工具:MAT内存分析工具

用MAT内存分析工具,找出引起内存没有释放的原因


发现是context没有释放,导致内存泄露,继续分析,找到没有引起GC的保持该引用的地方


找到最短的GC path,发现是Volley中德CacheDispacher保持了context的引用,导致没有引起GC释放内存。


但是volley框架内的东西怎么会引起这种问题?

首先想到在onDestroy中取消掉没有加载完的request。但是没有效果

google 了半天,终于在stackoverflow上找到了答案,大概的意思就是说,初始化RequestQueue的时候尽量使用全局的Context也就是ApplicationContext。

否则的话没有Activity都要维护一个volley请求队列以及分发线程、请求线程和缓存线程。

这样就会导致,在volley框架的内部保持了一个Activity的context引用,也就是说,当我们的Activity的生命周期结束了之后,volley中可能还有没走完的子线程中依然保留该context的引用,导致无法内存回收。

四、解决方法

首先,我们要保持项目中唯一一个Volley的RequestQueue,使用单例模式来实现

public class SingleRequestQueue {

    private static RequestQueue mQueue;

    private SingleRequestQueue(Context context) {
        mQueue = Volley.newRequestQueue(context);
    }

    public static synchronized RequestQueue getRequestQueue(Context context){
        if (mQueue == null){
            new SingleRequestQueue(context.getApplicationContext());
        }
        return mQueue;
    }
}

在统一一个类中处理网络请求。

另外,看到网上评论说当加载大的网络图片的时候不建议使用Volley,我用的是UniversalImageLoader。


推荐一篇文章讲解Android 中Context。点这里


总结:

之前一直没有遇到context上下文内存泄露的问题,这个问题很好地弥补了这方面的空白

通过这个问题的分析解决,加深了内存泄露的分析思路,同时也巩固了MAT内存分析工具的使用方法。

android网络开源框架volley(四)——谈谈图片加载

加载图片,这个几乎每个app都会有所涉及,然后就是如果流畅加载,如何管理好内存,避免OOM之类。这些东西,机会是每个程序员必须面对的一些挑战。这里介绍下关于volley加载图片的用法。...
  • ttdevs
  • ttdevs
  • 2014年02月17日 11:08
  • 7661

Volley框架中加载图片的3种方式

Volley框架中加载图片的3种方式
  • little_shengsheng
  • little_shengsheng
  • 2016年05月05日 16:47
  • 1066

Volley框架缓存过大导致oom

exception: java.lang.OutOfMemoryError: Failed to allocate a 1852142714 byte allocation with 83886...
  • y_chengyong
  • y_chengyong
  • 2015年10月23日 18:27
  • 4326

Android之Volley框架加载网络图片的三种方式

1.第一种也是最常用的一种:ImageLoader public void imageLoader(String url,ImageView iv){ //ImageLoader的第一...
  • ygd1994
  • ygd1994
  • 2016年05月08日 23:18
  • 1119

android Volley 上传文件上传图片

android volley 实现上传文件功能
  • com314159
  • com314159
  • 2014年10月07日 14:19
  • 54545

Android Volley完全解析(二),使用Volley加载网络图片

在上一篇文章中,我们了解了Volley到底是什么,以及它的基本用法。本篇文章中我们即将学习关于Volley更加高级的用法,如何你还没有看过我的上一篇文章的话,建议先去阅读Android Volley完...
  • sinyu890807
  • sinyu890807
  • 2014年04月17日 09:23
  • 148206

android框架搭建——二次封装Volley框架

上一篇博文中提到了自己写一个网络工具类,然而自己的能力明显有限,封装的工具类无论从功能还是性能上都比不上前辈大牛们已经完善好的网络框架,但是我们又想更加方便的使用大牛们的框架,怎么办呢?我们可以二次封...
  • cai554112503
  • cai554112503
  • 2015年11月29日 15:40
  • 2869

java OOM(OutOfMemory) 问题分析

偶然在工作中有发现部署的应用有内存溢出,所以抽空补充了一下这些方面的知识。 内存溢出我们可以通过heapDump来分析到底是那个对象吃掉过多内存而导致的。而heapDump我们可以使用一下方法获取: ...
  • sulong507
  • sulong507
  • 2016年06月16日 18:41
  • 1059

[安卓开发] ImageView加载图片内存溢出oom解决方案

工具类加一个静态方法: /** * 以最省内存的方式读取本地资源的图片 * @param context 上下文 * @param resId 资源Id ...
  • niubitianping
  • niubitianping
  • 2016年07月31日 15:38
  • 1941

Android 解决加载图片过多出现oom--强大的Fresco

Fresco是Facebook推出的很好的解决加载图片过多而产生的oom现象。但是在我最先接触Fresco的时候,由于我用的eclipse开发, 在官网下载的Fresco库没办法用,不知道是怎么回事,...
  • sunflower_cwy
  • sunflower_cwy
  • 2016年02月24日 11:29
  • 3378
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Andorid Volley框架加载图片OOM问题分析
举报原因:
原因补充:

(最多只允许输入30个字)