我正在尝试实现2个异步任务,其中一个应该等待另一个完成。
我为它做了一个测试用例,看起来像这样:
public class MainActivity extends Activity{
public static boolean SYNCING = false;
public static Object LOCK = new Object();
public static void setSync(){
Log.i(TAG, "setting Sync=true");
synchronized (LOCK) {
SYNCING = true;
}
}
public static void waitForSync(){
Log.i(TAG, "waiting for Sync");
synchronized (LOCK) {
try{
while (SYNCING){
LOCK.wait();
}
} catch (InterruptedException ignore){}
}
}
public static void setSyncFinish(){
Log.i(TAG, "setSyncFinish to notify all");
synchronized (LOCK) {
SYNCING = false;
LOCK.notifyAll();
}
}
public class WaitingOnLoaderTask extends AsyncTask<Void, Void, Void>{
@Override
protected Void doInBackground(Void... params) {
Log.i(TAG, "doInBackground of WaitingForLoaderTask");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
waitForSync();
Log.i(TAG, "finishedWaiting!");
return null;
}
}
public class LoaderTask extends AsyncTask<Void, Void, Void>{
long mRuntime;
int mTimes;
public LoaderTask(long runtime, int times){
mRuntime = runtime;
mTimes = times;
}
@Override
protected Void doInBackground(Void... params) {
while(mTimes >= 0){
Log.i(TAG, "sleeping for " + mTimes + " times for " + mRuntime + " milliseconds");
mTimes--;
try {
Thread.sleep(mRuntime);
} catch (InterruptedException e) {
Log.e("MainActivity", "Interrupted", e);
}
}
setSyncFinish();
return null;
}
}
}
但我无法让WaitingOnLoaderTask
正确等待。如果我在onCreate
new WaitingOnLoaderTask().execute((Void[])null);
new LoaderTask(1000, 5).execute((Void[])null);
我得到像这样的logOutput(发生死锁):
03-08 18:17:23.309: I/myUniqueLogTag(4432): setting Sync=true
03-08 18:17:23.317: I/myUniqueLogTag(4432): doInBackground of WaitingForLoaderTask
03-08 18:17:23.817: I/myUniqueLogTag(4432): waiting for Sync
和
new LoaderTask(1000, 5).execute((Void[])null);
new WaitingOnLoaderTask().execute((Void[])null);
我得到这样的日志:
03-08 18:18:53.082: I/myUniqueLogTag(4621): sleeping for 5 times for 1000 milliseconds
03-08 18:18:54.082: I/myUniqueLogTag(4621): sleeping for 4 times for 1000 milliseconds
03-08 18:18:55.090: I/myUniqueLogTag(4621): sleeping for 3 times for 1000 milliseconds
03-08 18:18:56.082: I/myUniqueLogTag(4621): sleeping for 2 times for 1000 milliseconds
03-08 18:18:57.090: I/myUniqueLogTag(4621): sleeping for 1 times for 1000 milliseconds
03-08 18:18:58.106: I/myUniqueLogTag(4621): sleeping for 0 times for 1000 milliseconds
03-08 18:18:59.113: I/myUniqueLogTag(4621): doInBackground of WaitingForLoaderTask
03-08 18:18:59.113: I/myUniqueLogTag(4621): setSyncFinish to notify all
03-08 18:18:59.621: I/myUniqueLogTag(4621): waiting for Sync
03-08 18:18:59.621: I/myUniqueLogTag(4621): finishedWaiting!
所以我猜一个人阻止对方跑。他们是否在同一个线程中实际计算了doInBackground
,并且LOCK.wait()
阻止此线程进一步执行?
有没有办法解决它(并与Android 2.2保持兼容)?
注意:
第二个时间基本上是我想要的,但在其他任务实现中,我不能保证WaitingOnLoaderTask
仅在另一个完成时执行。
答案 0 :(得分:1)
您最好的选择是使用Geobits建议。
您可以使用onPostExecute()函数调用下一个Async任务,以便它执行它:
class WaitingOnLoaderTask extends AsyncTask<Void,Void,Void>
{
protected void onPreExecute(Void)
{
super.onPreExecute();
}
protected void doInBackground(Void... params)
{
//Commands for first AsyncTask
}
protected void onPostExecute(Void)
{
//Call AsyncTask 2
}
}
这样它将等到任务1完成。
答案 1 :(得分:1)
您的代码在Android 3.2及更低版本上按预期工作。在更高版本的Android版本上,AsyncTasks没有并行执行,请尝试使其在Android 4 +上运行:
LoaderTask loaderTask = new LoaderTask(1000, 5);
WaitingOnLoaderTask waitingTask = new WaitingOnLoaderTask();
if (Build.VERSION.SDK_INT >= 14) {
loaderTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
waitingTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else {
loaderTask.execute();
waitingTask.execute();
}
注意:您应该将AsyncTasks标记为static
,以避免在配置更改(例如轮换)时泄漏活动。