非静态内部类/匿名类引起的Memory Leak
2016-05-20 11:25
573 查看
在最近使用okhttp3的过程中,使用LeakCanary检查发现引起了memory leak,排查后发现泄露发生在okhttp3.Callback中,顺便学习了非静态内部类/匿名类引起的内存泄漏问题,现摘录如下。
在JAVA中,非静态内部类/匿名类会隐式的持有外部类的引用,如果是外部类是Activity,在退出Activity后,系统不能回收Activity的资源,
导致内存泄漏。
解决这一问题,只需要将非静态内部类/匿名类改为静态的,静态的内部类/匿名类不会持有外部类的应用,这样系统就可以正常回收外部类的资源了。
“`
private static class UserBehaviorCallback implements okhttp3.Callback{
OkHttpClient client = OkHttpUtils.getInstance().getOkHttpClient();
在Android中,长时间运行的任务和Acyivity生命周期进行协调会有点困难,如果你不加以小心的话会导致内存泄漏。关于如何处理这个棘手的问题,下面有几个基本的技巧供参考
1、使用静态内部类/匿名类,不要使用非静态内部类/匿名类.非静态内部类/匿名类会隐式的持有外部类的引用,外部类就有可能发生泄漏。而静态内部类/匿名类不会隐式的持有外部类引用,外部类会以正常的方式回收,如果你想在静态内部类/匿名类中使用外部类的属性或方法时,可以显示的持有一个弱引用。
2、不要以为Java永远会帮你清理回收正在运行的threads.在上面的代码中,我们很容易误以为当Activity结束销毁时会帮我们把正在运行的thread也结束回收掉,但事情永远不是这样的!Java threads会一直存在,只有当线程运行完成或被杀死掉,线程才会被回收。所以我们应该养成为thread设置退出逻辑条件的习惯。
3、适当的考虑下是否应该使用线程.Android应用框架设计了许多的类来简化执行后台任务,我们可以使用与Activity生命周期相关联的Loaders来执行简短的后台查询任务。如果一个线程不依赖与Activity,我们还可以使用Service来执行后台任务,然后用BroadcastReceiver来向Activity报告结果。另外需要注意的是本文讨论的thread同样使用于AsyncTasks,AsyncTask同样也是由线程来实现,只不过使用了Java5.0新增并发包中的功能,但同时需要注意的是根据官方文档所说,AsyncTask适用于执行一些简短的后台任务
在JAVA中,非静态内部类/匿名类会隐式的持有外部类的引用,如果是外部类是Activity,在退出Activity后,系统不能回收Activity的资源,
导致内存泄漏。
解决这一问题,只需要将非静态内部类/匿名类改为静态的,静态的内部类/匿名类不会持有外部类的应用,这样系统就可以正常回收外部类的资源了。
“`
private static class UserBehaviorCallback implements okhttp3.Callback{
@Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { } }
OkHttpClient client = OkHttpUtils.getInstance().getOkHttpClient();
//192.168.192.102 --> 192.168.13.7 String json = new Gson().toJson(params); RequestBody body = RequestBody.create(JSON, json); okhttp3.Request request = new okhttp3.Request.Builder() .url("") .post(body) .build(); client.newCall(request).enqueue(new UserBehaviorCallback());
在Android中,长时间运行的任务和Acyivity生命周期进行协调会有点困难,如果你不加以小心的话会导致内存泄漏。关于如何处理这个棘手的问题,下面有几个基本的技巧供参考
1、使用静态内部类/匿名类,不要使用非静态内部类/匿名类.非静态内部类/匿名类会隐式的持有外部类的引用,外部类就有可能发生泄漏。而静态内部类/匿名类不会隐式的持有外部类引用,外部类会以正常的方式回收,如果你想在静态内部类/匿名类中使用外部类的属性或方法时,可以显示的持有一个弱引用。
2、不要以为Java永远会帮你清理回收正在运行的threads.在上面的代码中,我们很容易误以为当Activity结束销毁时会帮我们把正在运行的thread也结束回收掉,但事情永远不是这样的!Java threads会一直存在,只有当线程运行完成或被杀死掉,线程才会被回收。所以我们应该养成为thread设置退出逻辑条件的习惯。
3、适当的考虑下是否应该使用线程.Android应用框架设计了许多的类来简化执行后台任务,我们可以使用与Activity生命周期相关联的Loaders来执行简短的后台查询任务。如果一个线程不依赖与Activity,我们还可以使用Service来执行后台任务,然后用BroadcastReceiver来向Activity报告结果。另外需要注意的是本文讨论的thread同样使用于AsyncTasks,AsyncTask同样也是由线程来实现,只不过使用了Java5.0新增并发包中的功能,但同时需要注意的是根据官方文档所说,AsyncTask适用于执行一些简短的后台任务
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树