弱引用而不是getActivity()(Android避免内存泄漏)?

Max*_*ude 7 java android memory-leaks weak-references

为了避免内存泄漏,我编写了以下方法,该方法将用于活动,主要用于片段(使用继承).该方法应该允许我永远不会通过调用直接引用该活动

//this or getActivity()
Run Code Online (Sandbox Code Playgroud)

方法是:

private WeakReference<BaseActivity> activityWeakReference = null; 

public BaseActivity getActivityFromWeakReference(){
        activityWeakReference = activityWeakReference == null ?
                new WeakReference<BaseActivity>((BaseActivity)getActivity()) :
                activityWeakReference;
        return activityWeakReference.get();
    }
Run Code Online (Sandbox Code Playgroud)

根据内存泄漏威胁调用此方法getActivityFromWeakReference()而不是getActivity()安全吗?

如果这样做不安全,我应该返回activityWeakReference并调用其get()方法,以确保安全吗?

我一直在使用多个片段,到目前为止我没有任何问题.我问这个问题是因为我读到了这里(这里):

只要帮助者的生命周期在生命周期内 Activity,就没有必要使用WeakReference.如果帮助程序的寿命可以长于Activity,那么您应该使用a WeakReference 来避免Activity在系统破坏时保留对象图.

到目前为止,我还没有遇到一个被提及的元素超过活动的情况.如果您发现错误或可能的错误,请在评论中写下.

hqt*_*hqt 9

这完全可行.例如,你有这个伪代码代码:

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,有一种情况会导致内存泄漏.

这是解释:

当您DownloadTask按上面的示例创建时,java调用DownloadTask是一个内部类.内部类将隐式保存对外部类的引用,在本例中为MainActivity.而且,当你启动asynctask时,asynctask将由系统保存直到完成.例如,您下载需要30秒.在30秒内,您可以旋转设备.旋转设备时,MainActivity重新创建设备,并且通常会破坏旧活动.但是,在这种情况下,因为旧如旧的活性不被破坏,MainActivity例如通过持有DownloadTaskDownloadTask通过系统举行.您将泄漏一个活动实例.

要解决此问题,您应该将以上代码更改为:

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,当MainActivity创建new时,旧的不被保持DownloadTask(由于弱引用属性),因此旧的将在未来被Android垃圾收集器销毁.您还应该在每次使用弱引用对象时进行检查,因为您不确切知道GC何时会破坏这些对象.

这是我自己的博客关于内存泄漏的另一种情况.使用静态内部类时内存泄漏

希望这有帮助.

  • @MaximeClaude是的,基本上这是真的.你在"某个地方"保留你的活动的WeakReference,你应该把它作为你的方法(因为在某些情况下,它会为null因为GC已经清理了它)."某个地方"取决于很多情况,我的例子就是一个. (2认同)