android - 带有接口引用的内存泄漏
问题描述
我有一个关于内存泄漏的问题。我有两个课程。
第一个是:
public class Utility {
private static Utility instance = null;
private UpdateListener listener;
//Make it a Singleton class
private Utility(){}
public static Utility getInstance() {
if (instance == null)
instance = new Utility();
return instance;
}
public void setListener(UpdateListener listener) {
this.listener = listener;
}
//Long running background thread
public void startNewTread() {
new Thread (new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000 * 10);
if (listener != null)
listener.onUpdate();
} catch (InterruptedException e) {
Log.d("Utility", e.getMessage());
}
}
}).start();
}
//Listener interface
public interface UpdateListener {
public void onUpdate();
}
}
第二类是:
public class ListenerLeak extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Setting the listener
Utility.getInstance().setListener(new Utility.UpdateListener() {
@Override
public void onUpdate() {
Log.d("ListenerLeak", "Something is updated!");
}
});
//Starting a background thread
Utility.getInstance().startNewTread();
}
@Override
protected void onDestroy() {
super.onDestroy();
}
}
在这个活动中。新的 Utility.UpdateListener 可能会造成内存泄漏吗?当活动被破坏时,只有Updatelistener可以活着。活动可以活着吗?
解决方案
在 Utility 类中创建一个内部类,如下所示。然后将线程移动到该类。
public void startNewTread() {
new MyThread().start();
}
private static class MyThread extends Thread {
@Override
public void run() {
try {
Thread.sleep(1000 * 10);
if (listener != null)
listener.onUpdate();
} catch (InterruptedException e) {
Log.d("Utility", e.getMessage());
}
}
}
原因:每次配置更改后,Android 系统都会创建一个新的 Activity,并将旧的 Activity 留在后面进行垃圾回收。但是,线程持有对旧 Activity 的隐式引用,并阻止它被回收。结果,每个新的 Activity 都会被泄露,并且与它们相关的所有资源都永远无法回收。https://www.androiddesignpatterns.com/2013/04/activitys-threads-memory-leaks.html将有助于理解它。
推荐阅读
- javascript - 使用js打印图案
- javascript - 过渡效果仅在 Firefox 中有效
- php - 图像不保存到临时文件夹但保存到数据库
- javascript - 如何将 GeoJson 文件上传到数据库
- reactjs - Axios 使用登录用户的用户 ID 发布表单数据
- c# - 有没有办法在 SMO v16 nuget 包中禁用 TraceHelper?
- nestjs - TypeORM - 如何为实体定义数据库名称
- java - 我正在尝试获得组合,但我不知道该怎么做
- c - semop 调用中 EIDRM 和 EINVAL errno 之间的区别
- scmmanager - 无法通过 API 安装插件