弱引用而不是 getActivity()(Android 避免内存泄漏)?
Weak reference instead of getActivity() (Android avoid memory leak)?
为了避免内存泄漏,我编写了以下将在活动中使用的方法,主要用于片段(使用继承)。该方法应该允许我永远不会通过调用
直接引用 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()
是否安全?
如果这样做不安全,我是否应该 return activityWeakReference
并改为调用它的 get()
方法,以确保安全?
我一直在多个片段中使用它,到目前为止我没有遇到任何问题。我问这个问题是因为我读了这个 ():
As long as the lifetime of the helper is within the lifetime of the
Activity
, then there's no need to use a WeakReference
. If the helper
can live longer than the Activity
, then you should use a WeakReference
to avoid retaining the Activity
in your object graph when the system
destroys it.
到目前为止,我还没有遇到过引用元素超过 activity 的情况。如果您发现错误或可能的错误,请大家在评论中写出来。
有一些情况,如果你的片段设置为保留实例,它会比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. An inner class will implicit holds a reference to outer class, in this case is MainActivity
. Moreover, when you start an asynctask, that asynctask will be held by system until it finish. For example, you download takes 30 seconds. In that 30 seconds, you rotate your device. When you rotate your device, MainActivity
is 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
持有(由于弱引用属性),所以旧的将被[=销毁39=] 未来的垃圾收集器。您还应该在每次使用弱引用对象时进行检查,因为您不知道 GC 何时会销毁这些对象。
这里是我自己的博客,关于内存泄漏的另一种情况。 Memory leak when using static inner class
希望对您有所帮助。
为了避免内存泄漏,我编写了以下将在活动中使用的方法,主要用于片段(使用继承)。该方法应该允许我永远不会通过调用
直接引用 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()
是否安全?
如果这样做不安全,我是否应该 return activityWeakReference
并改为调用它的 get()
方法,以确保安全?
我一直在多个片段中使用它,到目前为止我没有遇到任何问题。我问这个问题是因为我读了这个 (
As long as the lifetime of the helper is within the lifetime of the
Activity
, then there's no need to use aWeakReference
. If the helper can live longer than theActivity
, then you should use aWeakReference
to avoid retaining theActivity
in your object graph when the system destroys it.
到目前为止,我还没有遇到过引用元素超过 activity 的情况。如果您发现错误或可能的错误,请大家在评论中写出来。
有一些情况,如果你的片段设置为保留实例,它会比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. An inner class will implicit holds a reference to outer class, in this case is MainActivity
. Moreover, when you start an asynctask, that asynctask will be held by system until it finish. For example, you download takes 30 seconds. In that 30 seconds, you rotate your device. When you rotate your device, MainActivity
is 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
持有(由于弱引用属性),所以旧的将被[=销毁39=] 未来的垃圾收集器。您还应该在每次使用弱引用对象时进行检查,因为您不知道 GC 何时会销毁这些对象。
这里是我自己的博客,关于内存泄漏的另一种情况。 Memory leak when using static inner class
希望对您有所帮助。