我可以把异步任务链接起来顺序执行吗?(即在前一个异步任务完成后开始执行下一个异步任务)

17
每次执行 httpRequest 时,代码会执行一段时间,导致屏幕会被锁定几秒钟。因此我使用了 AsyncTask 来在单独的线程中完成所有我的 httpRequest 操作,并显示一个 ProgressDialog,以便用户知道正在发生某些事情。
最近我遇到了以下情况:我的一个 httpRequest 的输入取决于之前的一个 httpRequest(+解析)操作的结果。我不能只是按顺序放置两个 AsyncTask,因为 Android 会将它们放入两个线程中并在第一个未完成的情况下开始第二个。如果没有适当的输入(第一个 httpRequest 的结果),我的第二个 httpRequest 将崩溃应用程序。
有没有办法加入 wait() 来强制第二个 AsyncTask 等待第一个结束后再开始?
6个回答

11

我也遇到了同样的情况。 我是这样解决的: 将你的Activity引用传递给异步类的构造函数,并执行doInBackground功能。现在在postExecute函数中,从异步类调用Activity的公共方法以再次执行任务...或尝试这个:

            if (asynclass.getStatus() == android.os.AsyncTask.Status.PENDING) {
                asynclass.execute();
            } else if (RF.getStatus() == android.os.AsyncTask.Status.FINISHED) {
                asynclass = new asyncclass();
                asynclass.execute();
            } else {
                Toast.maketoast(this, "Plz wait", 1).show();
            }

干杯


2
+1 同意 @Await 的观点,我们可以使用 getStatus() 方法获取任何 AsyncTask 的状态。 - Paresh Mayani
我考虑采用你和@nik建议的方法,只需在postExcute函数中调用第二个异步任务,但是在另一个异步任务中调用异步任务是否是不良实践? - adjfac

6

所以我认为(不确定),你需要在post execution方法中调用第二个异步任务。

protected void onPostExecute(final Void unused) {
            if (this.dialog.isShowing()) {
                this.dialog.dismiss();
                     new secTask().execute();
            }}

4

可以的。但是只能在onProgressUpdate()onPostExecute()方法中实现。您可以按照以下方式尝试实现:

private class Task1 extends AsyncTask<Void, Void, Void> {
...
...
    protected void onPostExecute(Void unused) { 
        dialog1.dismiss();
        new Task2().execute();
    }

}

同样地,你需要在Task2的AsyncTask的onPostExecute()方法中放置new Task3().execute();

不要在主代码中这样调用它们。如果你这样做,那么它们都会一起运行:

// This is wrong
new Task1().execute();
new Task2().execute();
new Task3().execute();

参考资料:异步任务


3

使用executOnExecutor方法如何呢:

public void runTasks() {

        AsyncTask<Void,Void,Void> aTask = myTask();
        AsyncTask<Void,Void,Integer> aTask1 = myTask1();
        AsyncTask<Void,Void,Void> aTask2 = myTask2();

        aTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
        aTask1.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
        aTask2.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);

    }

但这种方式无法创建某种流程控制。哦,我的错,您仍然可以在onPreExecute回调中实现。 - Daniel F

1

我偶然发现了这个帖子,想找一个比我目前使用的更好的解决方案,但它似乎仍然是最好的...

我的做法是在每个异步任务的构造函数中传递一个可运行对象。

要么在post execute中,要么在do in the background结束时,通过执行可运行对象启动下一个任务(如果有的话)。

 if(doOnPostExec != null)
        doOnPostExec.run();

这样我就可以通过传递的可运行对象改变异步任务的顺序,使代码更加灵活,如果不传递可运行对象,则它们会正常完成。这些可运行对象只包含一行调用下一个异步任务的代码。
我只是不喜欢创建那么多可运行对象。希望有像vb.net中链接委托的功能。

0

我之前遇到过这个问题。我的做法是使用回调接口类,在onPostExecute()方法内调用其方法。这样你就可以从回调方法中调用另一个AsyncTask。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接