SETUP:
我有一个单例应用程序类,它有一个名为fetchUpdates()
的方法。此方法由UpdaterService
(IntentService)类调用。 fetchUpdates()
方法只调用DownloadDataAsyncTask,如果数据成功下载,则会在UpdateDbAsyncTask
期间调用onPostExecute
。两个AsyncTasks都驻留在应用程序类中(不确定这是否与问题相关)。
public synchronized void fetchUpdates() {
String[] mURLs = getURLs();
new DownloadDataAsyncTask().execute(mURLs[0], mURLs[1]);
}
DownloadDataAsyncTask类
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中一切正常,但在API 10中的doInBackground之后暂停执行UpdateDbAsyncTask
。也不会调用onCancelled(Object)方法。
LOGCAT OUTPUT
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的threading rules表示:
根据我的理解(这不是很多,刚开始编程)第一个UpdateDbAsyncTask
在两个API中都完全执行,因为它不违反任何线程规则。但是第二个是违反其中一个线程规则,导致它在doInBackground之后停止执行,或者它完全超出了我的理解。
我还找到了其他类似issue的人。后来在问题中提出了
在我的代码中始终只使用AsyncTask类API15 +
但我也不太确定如何做到这一点。
非常感谢任何帮助。谢谢!
更新1
只有从Activity调用UpdaterService
IntentService类(在Application类中调用fetchUpdates()
方法)时才会出现问题。我在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));
,问题似乎不会持久。
答案 0 :(得分:6)
首先,IntentService中的代码执行已经在后台线程中运行。没有必要使用AsyncTask。
我发现这个错误并不奇怪。我很惊讶你的第二个AsyncTask被调用了。当您的IntentService完成调用fetchUpdates方法时,您的服务已完成,您的进程和/或线程可能被安排销毁/终止。根据操作系统的激进程度,可能会立即或几分钟后发生。这意味着你的代码将在一个死线程上运行,这就是所发生的事情。
解决方案: 不要在IntentService中使用AsyncTasks。相反,只需直接从IntentService中的AsyncTasks调用代码即可。
答案 1 :(得分:1)
解决方案很简单,在postExecute
的{{1}}中,只需这样做:
DownloadDataAsyncTask
答案 2 :(得分:0)