如何在AsyncTask的doInBackground()中获取WeakReference

时间:2018-02-09 18:50:15

标签: android android-asynctask weak-references

我有一个名为RetrieveCoverImageTask的班级。它从Track实例中的URL检索实际封面图像:

private class RetrieveCoverImageTask extends AsyncTask<Track, Void, Void> {

    private WeakReference<Context> context;

    RetrieveCoverImageTask(Context context) {
        this.context = new WeakReference<>(context);
    }

    // V1
    @Override
    protected Void doInBackground(Track... tracks) {
        Context context = this.context.get();
        if (context != null) {
            for (Track track : tracks) {
                try {
                    Bitmap bmp = Picasso.with(context).load(track.getCoverUrl()).get();
                    if (bmp != null) {
                        ByteArrayOutputStream stream = new ByteArrayOutputStream();
                        bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
                        track.setCoverImage(stream.toByteArray());
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    // V2
    @Override
    protected Void doInBackground(Track... tracks) {
        for (Track track : tracks) {
            try {
                Context context = this.context.get();
                if (context != null) {
                    Bitmap bmp = Picasso.with(context).load(track.getCoverUrl()).get();
                    if (bmp != null) {
                        ByteArrayOutputStream stream = new ByteArrayOutputStream();
                        bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
                        track.setCoverImage(stream.toByteArray());
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

来自Activity的示例来电如下:

new RetrieveCoverImageTask(context).execute(track1, track2, track3);

首先,我做了V1。然后,我认为使用Picasso进行图像检索需要时间,同时调用Activity可能会变为空,因此,我必须在for循环的每次迭代开始时获取上下文。这就是我实施V2的方式。

哪个版本的doInBackground()有效且无错误? V1或V2?

3 个答案:

答案 0 :(得分:0)

效率可能不是这里最大的问题。 V2更安全,但整件事情并不是很优雅&#34;。使用RxJava设置内容要容易得多。你不需要WeakReferences。关键是在上下文无效时处理您的订阅(例如onDestroy())并且您将检查保存为空。

此外,您可能希望使用一种方法来获取不涉及毕加索的bmp,​​因此不需要上下文。或者,只要应用程序正在运行,您就会使用存在的应用程序上下文,因此您不需要空检查

答案 1 :(得分:0)

WeakReference.get是正确的。

如果你想使用Picasso,可以直接在View(可能是onBindViewholder)上进行,因为它已经在后台执行了。

如果你想使用一个任务,你需要下载流而不是URLConnection才能有效,或者OkHttp(最新版本,导致它嵌入为URLConnection)

答案 2 :(得分:0)

在异步任务中使用Picasso毫无意义,因为Picasso无论如何都会在不同的线程上异步加载图像。此外,您将位图存储在变量中会占用大量内存,因为位图很重,所有这些都将存储在ram中,即使它们不是必需的。更好的方法是在Marcos Vasconcelos指出的ViewHolder中直接使用Picasso。