【问题标题】:Have external class call back to AsyncTask for progress update让外部类回调 AsyncTask 以进行进度更新
【发布时间】:2011-04-17 16:21:32
【问题描述】:

我正在运行一个活动,它必须从 Internet 下载一个相当大的图像,然后显示它。这可行:下载是通过 AsyncTask 完成的,并显示一个进度对话框。下载完成后,会调用显示图像的 Activity。

我遇到的问题是真正的工作是在外部类中完成的。这与其他活动调用相同的例程来获取图像一样。所以我不能立即调用 postUpdate() 来设置更新,因为这个调用将在另一个类中完成。现在我想知道如何将进度更新返回到我的 AsyncTask,以便我的进度对话框可以显示实际进度

AsyncTask 子类目前如下所示:

private class StartShowImage extends AsyncTask<String, Integer, String> {

    private ProgressDialog dialog;

    @Override
    protected void onPreExecute() {

        // Toon een dialog met draaiend wiel terwijl we de foto
        // aan het ophalen zijn.
        dialog = new ProgressDialog(ShowDeaddrop.this);
        dialog.setTitle(R.string.progress_dialog_title);
        dialog.setMessage(getResources().getString(
                R.string.progress_dialog_fetching_image));
        dialog.show();
    }

    /**
     * De hoofdroutine; haalt de foto op.
     */
    @Override
    protected String doInBackground(final String... params) {
        final String imageName = params[0];
        String result = null;
        try {
            result = DeaddropUtil.getImage(context, imageName, ""
                    + deaddropID, true);
        } catch (final IOException e) {
            Log.v(TAG, "Failed to download image " + imageName);
            Log.v(TAG, "" + e);
        }
        return result;
    }

    /**
     * Als we de foto hebben, start ShowImage.
     */
    @Override
    protected void onPostExecute(final String imageName) {
        dialog.dismiss();
        if (isActive)
            if (imageName == null)
                Toast.makeText(context, R.string.toast_show_image_failed,
                        Toast.LENGTH_SHORT).show();
            else {
                final Intent i = new Intent(ShowDeaddrop.this,
                        ShowImage.class);
                i.putExtra("imageName", imageName);
                startActivityForResult(i, SHOW_IMAGE);
            }
    }
     }

isActive 是一个布尔值,用于跟踪此活动是否处于活动状态 - 它在 onCreate 和 onResume 中设置,在 onPause 中取消设置。

我一直在研究广播意图 - 我已经看到了一个关于如何将这样的意图发送回主要活动的示例,但问题是监听器必须在 onResume/onPause 中注册/取消注册 -而 AsyncTask 是一个单独的线程。所以看来这种方法不能安全使用。

编辑重述问题,希望得到解决我问题的答案。

AsyncTask 设置进度对话框。

onExecute() 线程可以直接更新进度对话框。没问题。

实际工作是在一个外部类中完成的,因此该外部类知道进度信息,它必须以一种或另一种方式将其传回给 AsyncTask。

AsyncTask 必须有某种监听器、处理程序或外部类可以回调的东西,以便提供进度更新。

问题是:如何执行该过程的最后一部分?什么是合适的听众?如何实现这样的监听器?监听器最终进入哪个线程 - 像 .onPreExecute() 和 .onPostExecute() 这样的 UI 线程,还是来自 .doInBackground() 的工作线程?

【问题讨论】:

    标签: android progress-bar android-asynctask


    【解决方案1】:

    通过使用 BroadcastIntent 解决。

    主要活动创建BroadcastReceiver、IntentFilter和进度对话框; AsyncTask 注册/注销此接收器,并分别在 onPreExecute/onPostExecute 中显示/关闭对话框。

    在 onResume 和 onPause 中有额外的位,当活动本身不活动时没有活动的接收者。

    我花了一些时间来理解这个意图广播,但在那之后它是一个非常快速和简单的实现。

    【讨论】:

    • 虽然我看到一个意图可以做到这一点,你知道是否可以在启动异步任务的原始类中创建回调?我只是担心提高意图和倾听可能产生的任何开销......?
    【解决方案2】:

    如果我理解正确,您希望从异步任务更新进度条。我可能会查看异步任务的 onProgressUpdate。 http://developer.android.com/reference/android/os/AsyncTask.html

    【讨论】:

    • 这不是问题。我的 AsyncTask 进程在一个单独的类中调用一个工作进程,而这个单独的类必须与 AsyncTask 进行通信。我怎样才能得到这个通讯?之后进度条的更新就很简单了。
    • 好的,我想我现在明白了。是的,这有点棘手,因为您不需要广播接收器不清理。我可能会推荐两种方法来处理这个问题。 1. 在 oncreate 事件中初始化你的进度对话框并创建一个广播接收器。然后检查 progressdialog.isShowing 并在从外部类发送数据时更新进度。 2. 可能会考虑使用服务而不是异步任务,这样广播接收器就会在服务启动和停止时进行设置和清理。
    • 我也在想类似的事情。但是必须在主类中实现它,而不是像 AsyncTask 系统应该的那样干净。这似乎是唯一的方法......
    【解决方案3】:

    您的班级StartShowImage 没有成员。这个对象也用于创建吐司。如果你为它创建成员Activity 和构造声明,你可以在调用它是你想要做的公共方法之前通过这样的构造函数初始化它:

    private Activity context;
    public StartShowImage(Activity context){
        this.context=context;
    }
    
    StartShowImage object=new StartShowImage(this)
    object.postUpdate();
    

    这应该可以工作,你的调用类应该扩展Activity

    【讨论】:

    • 此答案也无法解决实际问题,即如何将进度更新从外部类传回此 AsyncTask。之后更新进度条变得微不足道。如果只有我有所需的信息...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-08
    • 2011-12-17
    • 1970-01-01
    相关资源
    最近更新 更多