Volley内存溢出, Volley使用者快来看看,也许你也会遇到

果果大 2015-09-25 09:30:49
这几天发现Volley的网络请求有内存溢出现象。(检测工具是MAT,LeakCanary)
感觉现象很常见,也许大家还没发现,或着已经解决。
public class HeapTestActivity extends Activity {
TextView heapText;
/** Volley框架的请求队列 **/
public RequestQueue mRequestQueue ;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.heap_test);
mRequestQueue= Volley.newRequestQueue(this);
heapText=(TextView)findViewById(R.id.heapText);
getData();
}
String url="http://route.showapi.com/341-2";//笑话大全的API接口
HashMap<String, String> postMap;
public void getData() {
postMap = new HashMap<>();
postMap.put("showapi_appid", "10073");
postMap.put("showapi_sign", "8131cde1a4234008b25f2450e515607c");
postMap.put("showapi_timestamp", DateUtil.getOrderNum());
StringRequest arrayPostRequest = new StringRequest(Request.Method.POST,url, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
//请求成功
heapText.setText(response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
//请求错误
}
}) {
@Override
protected Map<String, String> getParams() {
return postMap;
}
};
arrayPostRequest.setTag("StringRequest");
mRequestQueue.add(arrayPostRequest);
}

@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
mRequestQueue.cancelAll(this);
}

}


此代码大家可以直接COPY就能运行。

LeakCanary显示:StringRequest的参数,有个匿名内部类监听一直持有HeapTestActivity 这个对象,导致无法释放。
MAT显示如下图:
...全文
432 4 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
yunluoxing734501 2016-11-19
  • 打赏
  • 举报
回复
我觉得,楼上回复的都不是重点!Queue 用单例来封装是对的,但是内存泄漏明显不是因为是不是单例原因造成的,是因为楼主写的 new Response.Listener<String>() 这句使用了内部匿名类,因为他初始化的时候是在HeapTestActivity 里面自动生成一个内部类,那么这个内部类没有执行完毕的时候,是持有HeapTestActivity 的引用的,导致HeapTestActivity 不能被回收,从而导致内存泄漏! 同意的点赞!不同意的来板砖!
RunningShadow_007 2015-10-04
  • 打赏
  • 举报
回复
使用单例模式,下面是google官方给的example
public class MySingleton {
    private static MySingleton mInstance;
    private RequestQueue mRequestQueue;
    private ImageLoader mImageLoader;
    private static Context mCtx;

    private MySingleton(Context context) {
        mCtx = context;
        mRequestQueue = getRequestQueue();

        mImageLoader = new ImageLoader(mRequestQueue,
                new ImageLoader.ImageCache() {
            private final LruCache<String, Bitmap>
                    cache = new LruCache<String, Bitmap>(20);

            @Override
            public Bitmap getBitmap(String url) {
                return cache.get(url);
            }

            @Override
            public void putBitmap(String url, Bitmap bitmap) {
                cache.put(url, bitmap);
            }
        });
    }

    public static synchronized MySingleton getInstance(Context context) {
        if (mInstance == null) {
            mInstance = new MySingleton(context);
        }
        return mInstance;
    }

    public RequestQueue getRequestQueue() {
        if (mRequestQueue == null) {
            // getApplicationContext() is key, it keeps you from leaking the
            // Activity or BroadcastReceiver if someone passes one in.
            mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext());
        }
        return mRequestQueue;
    }

    public <T> void addToRequestQueue(Request<T> req) {
        getRequestQueue().add(req);
    }

    public ImageLoader getImageLoader() {
        return mImageLoader;
    }
}
Here are some examples of performing RequestQueue operations using the singleton class:

// Get a RequestQueue
RequestQueue queue = MySingleton.getInstance(this.getApplicationContext()).
    getRequestQueue();

// ...

// Add a request (in this example, called stringRequest) to your RequestQueue.
MySingleton.getInstance(this).addToRequestQueue(stringRequest);
大-大-熊 2015-10-02
  • 打赏
  • 举报
回复
楼上正角,必须只持有一个RequestQueue
飞翔的超人 2015-09-30
  • 打赏
  • 举报
回复
整个项目中用一个RequestQueue ,可以弄成单例模式。官网上有写,然后创建RequestQueue 的时候用Application的context。If your application makes constant use of the network, it's probably most efficient to set up a single instance of RequestQueue that will last the lifetime of your app. You can achieve this in various ways. The recommended approach is to implement a singleton class that encapsulates RequestQueue and other Volley functionality. Another approach is to subclass Application and set up the RequestQueue in Application.onCreate(). But this approach is discouraged; a static singleton can provide the same functionality in a more modular way.

A key concept is that the RequestQueue must be instantiated with the Application context, not an Activity context. This ensures that the RequestQueue will last for the lifetime of your app, instead of being recreated every time the activity is recreated (for example, when the user rotates the device).

80,471

社区成员

发帖
与我相关
我的任务
社区描述
移动平台 Android
androidandroid-studioandroidx 技术论坛(原bbs)
社区管理员
  • Android
  • yechaoa
  • 失落夏天
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧