为了避免内存泄漏,我编写了以下方法,该方法将在 Activity 中以及主要在 fragment 中使用(使用继承)。该方法应该允许我从不直接通过调用来引用 Activity
//this or getActivity()
该方法是:
private WeakReference<BaseActivity> activityWeakReference = null;
public BaseActivity getActivityFromWeakReference(){
activityWeakReference = activityWeakReference == null ?
new WeakReference<BaseActivity>((BaseActivity)getActivity()) :
activityWeakReference;
return activityWeakReference.get();
}
根据内存泄漏威胁,调用此方法
getActivityFromWeakReference()
而不是getActivity()
是安全的吗?如果这样做不安全,那么我应该返回
activityWeakReference
并调用其get()
方法来使其安全吗?我已经在多个 fragment 中使用它,到目前为止我还没有遇到任何问题。我问这个问题,因为我读了这个(here):
到目前为止,我还没有遇到过这样的情况:所引用的元素比 Activity 的生命周期更长。如果您发现错误或可能的错误,请在注释中写出来。
最佳答案
这是完全可行的。例如,您具有以下伪代码:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new DownloadTask().execute();
}
public void showInfo() {
}
class DownloadTask extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
return null;
}
@Override
protected void onPostExecute(Void data) {
// we can call showInfo() activity because Asynctask hold an implicit reference to activity
showInfo();
}
}
}
在上面的代码中,有一种情况会导致内存泄漏。
这里是解释:
当您按照上述示例创建
DownloadTask
时,java调用DownloadTask
是inner class。内部类隐式拥有对外部类的引用,在这种情况下为MainActivity
。此外,当您启动asynctask时,该asynctask将由系统保留直到完成。例如,下载需要30秒。在这30秒钟内,您旋转设备。旋转设备时,MainActivity
为re-created,通常旧的 Activity 将被破坏。但是在这种情况下,旧的 Activity 不会被破坏,因为旧的MainActivity
实例由DownloadTask
保留,而DownloadTask
由系统保留。您将泄漏一个 Activity 实例。为了解决这个问题,您应该将上面的代码更改为:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new DownloadTask(this).execute();
}
public void showInfo() {
}
}
class DownloadTask extends AsyncTask<Void, Void, Void> {
WeakReference<MainActivity> mainActivityWeakReference;
public DownloadTask(MainActivity activity) {
mainActivityWeakReference = new WeakReference<MainActivity>(activity);
}
@Override
protected Void doInBackground(Void... params) {
return null;
}
@Override
protected void onPostExecute(Void data) {
if (mainActivityWeakReference.get() != null) {
mainActivityWeakReference.get().showInfo();
}
}
}
在这种情况下,当创建新的
MainActivity
时,DownloadTask
不会保留旧的ojit_code(由于引用属性较弱),因此将来会被Android Garbage Collector销毁。您还应该在每次使用弱引用对象时进行检查,因为您不知道确切的时间GC将销毁那些对象。这是我自己的博客,涉及内存泄漏的另一种情况。 Memory leak when using static inner class
希望对您有所帮助。