我应该在AsyncTask中使用WeakReference <context>或Application Context吗?

时间:2017-01-19 16:55:41

标签: android

我有点陷入两难境地,我希望你们可以帮助我。

正如您所看到的,我有一个AsyncTask我在其中有一些代码将Bitmap个对象保存为.jpg文件到库中。在AsyncTask我也使用Context,但据我所知,在此内部类中使用Activity的上下文可能会导致内存泄漏,因此我将其更改为WeakReference<Context> weakContext;所以垃圾收集器可以收集它。

但是通过使用我从构造函数中传递的Application得到的View上下文,我应该归档与弱上下文引用相同的效果

在这种情况下,使用它比其他更好吗?

public class ViewToBitmap {

private View view;
private WeakReference<Context> weakContext;

public ViewToBitmap(@NonNull View view) {
    this.view = view;
}

 // This?
private WeakReference<Context> getContext() {
    weakContext = new WeakReference<>(view.getContext());
    return weakContext;
}

 // Or This?
private Context getContext() {
    return view.getContext().getApplicationContext();
}

private class AsyncSaveBitmap 
                extends AsyncTask<Void, Void, Void> 
                implements MediaScannerConnection.OnScanCompletedListener {

    @Override
    protected Void doInBackground(Void... params) {
      //TODO: Save bitmaps to gallery
      //CONTEXT IS USED HERE
       getContext().get()
       return null;
    }
}

1 个答案:

答案 0 :(得分:3)

由于View对象明确引用Context,这是在查看通货膨胀后使用的,因此您实际上是在保持&#34;传递性&#34;通过对Context进行严格引用,在ViewToBitmap的实例中对View进行硬性引用。

此外,由于AsyncSaveBitmap不是static,因此此类的实例隐含了对ViewToBitmap的封闭实例的引用。

最终结果是,只要AsyncSaveBitmap存在,就会有一系列对Activity的硬引用会阻止GC Activity

所以,答案是:两种方法都不够好。

最好的方法是重构逻辑,使得长时间运行的代码不会引用ContextActivityView等。

实现这一目标最直接的方法是使用Observer设计模式或Publish-Subscribe设计模式 - 这样你可以&#34;取消注册&#34;在生命周期方法中(例如onStop()),从而删除了潜在危险的引用并防止内存泄漏。

修改

出于图书馆目的,您不一定需要特定的Context和应用程序Context就足够了,可以使用以下模式(取决于您的库是否暴露)如单身或不单身):

// Use this approach if clients will use your library as Singleton
private static Context sAppContext;

public static void init(Context context) {
    sAppContext = context.getApplicationContext();
}

// Use this approach if clients will instantiate your library's object on each use
private final Context mAppContext;

public MyLibraryEntryClass(Context context) {
    mAppContext = context.getApplicationContext();
}