1

我正在开发一个 Android 应用程序,该应用程序必须发出服务器请求,然后在请求完成时执行操作。这里有一些伪代码来帮助解释这种情况:

makeRequest(new SomeTask{
    onDone() {
        // Do actionB with queue
    }
});

// Do actionA with queue.  Must be execute first!!

这是makeRequest伪代码中的实现:

makeRequest(SomeTask task) {
    if(canDoOptimization) { // if true, don't need to make request

        // It's a bad idea to execute this immediately.
        // Wish I could wait until the current thread of execution was done...
        task.onDone();
        return;
    }

    asyncTask = new AsyncTask<SomeTask, Void, Void>() {
        doInBackground(SomeTask... task) {
            // Make server request...

            task.onDone();
        }
    }
    asyncTask.execute(task);
}

通常在预期actionA之前发生actionB,但在我们可以避免网络请求的情况下,SomeTask.execute会立即调用。这导致之前actionB发生,这是不好的。有什么办法可以保证这不会发生吗? actionA

我在javascript中多次遇到这种情况。在这些情况下,我会用 a or包装SomeTask.execute调用以保持正确的异步语义。setTimeoutsetImmediate

为清楚起见,以下是 JavaScript 中相同错误的示例:https ://gist.github.com/xavi-/5882483

知道我应该在 Java/Android 中做什么吗?

4

3 回答 3

1

欢迎来到同步世界。互斥或锁定对象通常用于此目的。Java中有互斥锁吗?

您的 B 任务应该等待任务 A 在完成时发出信号的互斥锁。这将确保正确的执行顺序,其中 A 任务将在 B 之前完成。

于 2013-06-27T19:36:26.447 回答
1

始终放入task.onDone()AsyncTask即使它不必提出请求。

makeRequest(SomeTask task) {

    asyncTask = new AsyncTask<SomeTask, Void, Void>() {
        void doInBackground(SomeTask... task) {

            if(canDoOptimization) { // if true, don't need to make request

                // It's a bad idea to execute this immediately.
                // Wish I could wait until the current thread of was done...
                task.onDone();
                return;
            } else {
                // Make server request...

                task.onDone();
            }
        }
    }
    asyncTask.execute(task);
}
于 2013-06-27T20:53:22.770 回答
0

为什么你不能只是改变事物的顺序?

// Do actionA with queue.  Must be execute first!!

makeRequest(new SomeTask{
onDone() {
    // Do actionB with queue
});

如果 actionA 也是异步的并且在单独的 AsyncTask 上执行,您可以在 actionA 的 AsyncTasks 的 onPostExecute() 方法上调用 makeRequest(...)。

顺便说一句,从 Android Honeycomb 版本开始,AsyncTasks 在同一个线程上运行,这意味着如果您有多个任务,它们可以相互阻塞。通过指定 AsyncTsak 应在线程池中运行来解决此问题:

if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB) {
asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
else {
  asyncTask.execute();
}
于 2013-06-28T05:32:41.900 回答