【问题标题】:Setting Wallpaper of Firebase Storage Image inside an AsyncTask在 AsyncTask 中设置 Firebase 存储图像的墙纸
【发布时间】:2019-01-31 09:00:00
【问题描述】:

我在设置我的设备壁纸时遇到了一点麻烦,同时我的 Firebase 存储代码和 AsyncTask 在里面。

首先,将这段代码包含在 AsyncTask 中是否合适?

其次,壁纸已成功下载并设置,但由于某种原因,AsyncTask 在关闭 ProgressDialog 并显示 Toast 告诉我壁纸已设置之前并没有等待完成成功地。这里可能出了什么问题?

第三,尽管代码在 AsyncTask 的 doInBackground() 中,但它似乎并没有真正独立于主线程运行,因为我的应用程序在代码运行时完全冻结运行(并最终在完成后解冻)。

对我有什么见解吗?我边走边学,很困惑。

下面是代码供参考。

private class wallpaperTaskHome extends AsyncTask<Void, Void, String> {

    private ProgressDialog dialog = new ProgressDialog(PhotoDetailsActivity.this);

onPreExecute()

    @Override
    protected void onPreExecute() {

        // Progress dialog to show user that the app is working...
        dialog.setCancelable(false);
        dialog.setCanceledOnTouchOutside(false);
        dialog.setMessage(getString(R.string.wallpaper_please_wait));
        dialog.show();
    }

doInBackground()

    @Override
    protected String doInBackground(Void... params) {

        // Get Intent data from intent passed from Photos.java class.
        Intent intent = getIntent();
        int position = intent.getExtras().getInt("Image int");

        final StorageReference fullSizeImagesStoragePath = mStorageRef.child("images_full_size/" + position + ".jpg");
        fullSizeImagesStoragePath.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
            @Override
            public void onSuccess(Uri uri) {

                // Retrieve a WallpaperManager
                final WallpaperManager wallpaperManager = WallpaperManager
                        .getInstance(PhotoDetailsActivity.this);

                Glide
                        .with(PhotoDetailsActivity.this)
                        .asBitmap()
                        .load(uri)
                        .into(new SimpleTarget<Bitmap>() {
                            @Override
                            public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
                                try {
                                    wallpaperManager.setBitmap(resource, null, true, WallpaperManager.FLAG_SYSTEM);
                                } catch (IOException e) {
                                }
                            }
                        });
            }
        });
        return null;
    }

onPostExecute()

    protected void onPostExecute(String result) {

        if (dialog.isShowing()) {
            dialog.dismiss();
        }

        // Show a Toast message on successful wallpaper change
        showToastWallpaperApplied();
    }
}

感谢您为我提供的任何帮助!

编辑:我已将我的 doInBackground() 方法更改为如下所示,它基本上做同样的事情,但现在至少它正在尝试异步调用整个代码,因为它给了我错误:java.lang.IllegalArgumentException: You must call this method on the main thread

final WallpaperManager wallpaperManager = WallpaperManager
            .getInstance(this);

    Intent intent = getIntent();
    int position = intent.getExtras().getInt("Image int");

    final StorageReference fullSizeImagesStoragePath = mStorageRef.child("images_full_size/" + position + ".jpg");
    GlideApp.with(PhotoDetailsActivity.this)
            .asBitmap()
            .load(fullSizeImagesStoragePath)
            .into(new SimpleTarget<Bitmap>() {
                @Override
                public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
                    try {
                        wallpaperManager.setBitmap(resource, null, true, WallpaperManager.FLAG_SYSTEM);
                    } catch (IOException e) {
                    }
                }
            });

它指向.into(new SimpleTarget&lt;Bitmap&gt;() 作为只希望在主线程上运行的方法。帮忙?

【问题讨论】:

    标签: android android-asynctask firebase-storage freeze android-wallpaper


    【解决方案1】:

    我的猜测是 glide 内部会在 UI 线程上调用 onSuccess,然后你设置壁纸的任务仍然在 ui 线程上运行,即使你将它包装在异步任务中。我建议你检查一下 glide 相关方法的实现。

    编辑: 如果是这种情况,那么您也需要将设置的墙纸任务包装到异步任务中,这将非常繁琐。我的建议是使用 Rxjava 将这些任务链接在一起,这将是一个更好的方法。

    编辑: 看了看文档, https://github.com/bumptech/glide/wiki/Loading-and-Caching-on-Background-Threads 它说

    如果您确实想与背景上的解码图像进行交互 线程,而不是使用 downloadOnly 你可以使用的版本 into() 返回一个 FutureTarget

    因此,您可以尝试在后台线程(通过异步任务)上同步加载图像以避免阻塞 ui,但请确保使用应用程序上下文调用它以避免内存泄漏。

    Bitmap myBitmap = Glide.with(applicationContext)
        .load(yourUrl)
        .asBitmap()
        .centerCrop()
        .into(500, 500)
        .get()
    

    【讨论】:

    • 感谢您的评论!是否有任何代码示例可以执行类似这些功能的功能,您可以参考我(无论是 Rxjava 方法还是其他方法)?我不完全确定我应该从哪里开始了解如何针对我的特定需求实施这些方法。
    • 每次我尝试在 Async 方法中调用 .into(new SimpleTarget&lt;Bitmap&gt;() 时,都会收到错误:IllegalArgumentException: You must call this method on the main thread。我没有其他方法可以做到这一点吗?显然将这个函数放在非异步环境中会导致应用程序像往常一样冻结,因为它是在主线程上调用的......我该怎么办?
    • 我已经编辑了答案,你可以试试这个方法
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多