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内存分析工具的使用方法。

相关文章推荐

Volley框架缓存过大导致oom

exception: java.lang.OutOfMemoryError: Failed to allocate a 1852142714 byte allocation with 83886...

Android Volley的请求封装,实现图片内存缓存(防止OOM),数据磁盘缓存,及清除磁盘缓存

平时经常用到Volley请求网络数据,因为它确实好用,简单方便,因为项目要求也不是很苛刻,所以。。。。 呃。。。程序员总会去重构自己的代码,这不,我自己研究源码和网上的一些方法,重构了自己方便用的代码...

Android高效加载大图、多图解决方案,有效避免程序OOM

我们在编写Android程序的时候经常要用到许多图片,不同图片总是会有不同的形状、不同的大小,但在大多数情况下,这些图片都会大于我们程序所需要的大小。比如说系统图片库里展示的图片大都是用手机摄像头拍出...

四大组件之BroadCastReceiver(无序广播和有序广播)

实际开发中,有时会用到广播。广播分两种:无序广播和有序广播。注册的时候也同样分为静态注册和动态注册,具体什么情况下该选择哪种方式,我只能说:根据需求。 下面是代码,不赘述,注释说明也比较详细,我相信...

android设备的内存空间(RAM)总空间和可用空间大小的获取以及一些思考

在项目中我们会遇到这样的需求,那就是获取android设备可用内存(ram)空间的大小和总空间的大小.关于这个问题我们分为两个部分探讨.   一,通常情况下我们使用系统提供的api获取可用内存控件和总...

android-----Volley框架使用ImageLoader加载图片源码分析

上一篇我们分析了Volley框架的源码,知道了使用Volley框架的三个步骤,如果你对此还不是很熟,希望能看看上一篇博文:android-----Volley框架源码分析,这篇我们将首先使用Volle...

Android学习笔记:Andorid网络请求框架Volley的使用(中)--网络图片加载

对上一篇笔记《Android学习笔记:Andorid网络请求框架Volley的使用(上)》一个小补充:我们用Volley请求数据,不要忘记在AndroidManifest.xml中添加网络访问权限。今...
  • true100
  • true100
  • 2015年08月26日 14:14
  • 873

Android之批量加载图片OOM问题解决方案

一、OOM问题出现的场景和原因   一个好的app总少不了精美的图片,所以Android开发中图片的加载总是避免不了的,而在加载图片过程中,如果处理不当则会出现OOM的问题。那么如何...

android加载图片OOM问题

当在android应用中加载一张高分辨率的图片时,十分容易出现Out of memory(OOM),这是由于内存溢出造成的,每个应用所使用的堆内存大小一般是固定的,有的是16M,有的可能会大些。那为什...

Android开发解决加载图片OOM问题(非常全面 兼顾4.0以下系统)(by 星空武哥)

Android系统的手机在系统底层指定了堆内存的上限值,大部分手机的缺省值是16MB,不过也有些高配置的机型是24MB的,所以我们的程序在申请内存空间时,为了确保能够成功申请到内存空间,应该保证当前已...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Andorid Volley框架加载图片OOM问题分析
举报原因:
原因补充:

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