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

前端之家收集整理的这篇文章主要介绍了java – 弱引用而不是getActivity()(Android避免内存泄漏)?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
为了避免内存泄漏,我编写了以下方法,该方法将用于活动,主要用于片段(使用继承).该方法应该允许我永远不会通过调用直接引用该活动
//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()方法,以使其安全吗?

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

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.

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

解决方法

这完全可行.例如,你有这个伪代码代码
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,并且通常会破坏旧活动.但在这种情况下,旧的活动不会被破坏,因为旧的MainActivity实例由DownloadTask保存,而DownloadTask由系统保留.您将泄漏一个活动实例.

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

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> {
    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时,旧的MainActivity不会被DownloadTask保留(由于弱引用属性),因此旧的将在未来被Android垃圾收集器销毁.您还应该在每次使用弱引用对象时进行检查,因为您不确切知道GC何时会破坏这些对象.

这是我自己的博客关于内存泄漏的另一种情况. Memory leak when using static inner class

希望这有帮助.

猜你在找的Java相关文章