设置:
我有一个单例应用程序类,它有一个名为fetchUpdates()
. 此方法由UpdaterService
(一个 IntentService)类调用。fetchUpdates()
方法只需调用 DownloadDataAsyncTask,如果数据成功下载,则在调用UpdateDbAsyncTask
期间调用。onPostExecute
两个 AsyncTask 都驻留在应用程序类中(不确定这是否与问题相关)。
public synchronized void fetchUpdates() {
String[] mURLs = getURLs();
new DownloadDataAsyncTask().execute(mURLs[0], mURLs[1]);
}
下载DataAsyncTask 类
private class DownloadDataAsyncTask extends AsyncTask<String, Void, JSONObject[]> {
@Override
protected synchronized JSONObject[] doInBackground(String... params) {
String urlData = (String) params[0];
String urlId = (String) params[1];
JSONObject[] jSON = new JSONObject[] {
JSONfunctions.getJSONfromURL(urlData),
JSONfunctions.getJSONfromURL(urlId) };
return mJSON;
}
@Override
protected void onPostExecute(JSONObject[] result) {
if (result[0] != null && result[1] != null) {
new UpdateDbAsyncTask().execute(result[0], result[1]);
} else {
displayFailureToast();
}
}
}
UpdateDbAsyncTask 类
private class UpdateDbAsyncTask extends AsyncTask<JSONObject, Void, int[]> {
@Override
protected synchronized int[] doInBackground(JSONObject... params) {
Log.d(TAG, "UpdateDbAsyncTask doInBackground BEGIN");
int[] info = updateDb(params[0], params[1]);
Log.d(TAG, "UpdateDbAsyncTask doInBackground RETURNING RESULT");
return info
}
@Override
protected void onPostExecute(int[] result) {
Log.d(TAG, "UpdateDbAsyncTask onPostExecute BEGIN");
if (result[0] > 0) makeNotification(0);
if (result[1] > 0) makeNotification(1);
}
}
问题:
在 API 16 中一切正常,但UpdateDbAsyncTask
在 API 10 中的 doInBackground 之后执行暂停。也没有调用 onCancelled(Object) 方法。
LOGCAT 输出
06-22 16:11:51.047: D/dalvikvm(499): VFY: replacing opcode 0x6e at 0x0089
06-22 16:11:51.057: D/dalvikvm(499): VFY: dead code 0x008c-008e in Lcom/daybreak/android/test/MyApplication$UpdateDbAsyncTask;.onPostExecute ([I)V
06-22 16:11:51.087: D/MyApplication(499): UpdateDbAsyncTask doInBackground BEGIN
06-22 16:11:51.187: D/MyApplication(499): UpdateDbAsyncTask doInBackground RETURNING RESULT
06-22 16:11:51.197: W/MessageQueue(499): Handler{40567510} sending message to a Handler on a dead thread
06-22 16:11:51.197: W/MessageQueue(499): java.lang.RuntimeException: Handler{40567510} sending message to a Handler on a dead thread
06-22 16:11:51.197: W/MessageQueue(499): at android.os.MessageQueue.enqueueMessage(MessageQueue.java:196)
06-22 16:11:51.197: W/MessageQueue(499): at android.os.Handler.sendMessageAtTime(Handler.java:457)
06-22 16:11:51.197: W/MessageQueue(499): at android.os.Handler.sendMessageDelayed(Handler.java:430)
06-22 16:11:51.197: W/MessageQueue(499): at android.os.Handler.sendMessage(Handler.java:367)
06-22 16:11:51.197: W/MessageQueue(499): at android.os.Message.sendToTarget(Message.java:349)
06-22 16:11:51.197: W/MessageQueue(499): at android.os.AsyncTask$3.done(AsyncTask.java:214)
06-22 16:11:51.197: W/MessageQueue(499): at java.util.concurrent.FutureTask$Sync.innerSet(FutureTask.java:253)
06-22 16:11:51.197: W/MessageQueue(499): at java.util.concurrent.FutureTask.set(FutureTask.java:113)
06-22 16:11:51.197: W/MessageQueue(499): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:311)
06-22 16:11:51.197: W/MessageQueue(499): at java.util.concurrent.FutureTask.run(FutureTask.java:138)
06-22 16:11:51.197: W/MessageQueue(499): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
06-22 16:11:51.197: W/MessageQueue(499): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
06-22 16:11:51.197: W/MessageQueue(499): at java.lang.Thread.run(Thread.java:1019)
06-22 16:11:55.717: W/GAV2(499): Thread[Service Reconnect,5,main]: Service unavailable (code=1), using local store.
进一步的研究
AsyncTask的线程规则指出:
- AsyncTask 类必须在 UI 线程上加载。这是从 JELLY_BEAN 自动完成的。
- 任务实例必须在 UI 线程上创建。
- 必须在 UI 线程上调用 execute(Params...)。
- ETC...
据我了解(不多,刚开始编程),第一个UpdateDbAsyncTask
完全在两个 API 中执行,因为它不违反任何线程规则。但是第二个要么违反了线程规则之一,导致它在 doInBackground 之后停止执行,要么完全超出了我的理解。
我还发现其他人也有类似的问题。后来在问题中建议
只需在我的代码中始终使用 API15+ 的 AsyncTask 类
但我也不太确定该怎么做。
任何帮助将非常感激。谢谢!
更新 1
仅当我从 Activity 调用UpdaterService
IntentService 类(调用fetchUpdates()
Application 类中的方法)时才会出现问题。我的代码MainActivity
如下:
startService(new Intent(this, UpdaterService.class));
但是,当我fetchUpdates()
直接使用代码调用时
MyApplication myApp = (MyApplication) getApplication();
myApp.fetchUpdates();
从 开始MainActivity
,一切都在 API 10 中完美执行。
还要注意,UpdaterService
还使用一个BroadcastReceiver
类调用,该类设置为使用重复警报定期调用。在这种情况下,AsyncTasks 按预期执行......非常奇怪。
更新 2
Streets Of Boston的答案似乎是正确的答案。但是,奇怪的是,以下似乎也有效:
runOnUiThread(new Runnable() {
public void run() {
Intent serviceIntent = new Intent();
serviceIntent.setClass(getApplicationContext(), UpdaterService.class);
startService(serviceIntent);
}
});
我使用上面的代码从而不是开始IntentService
,问题似乎并没有持续存在。MainActivity
startService(new Intent(this, UpdaterService.class));