gpt4 book ai didi

android - onPostExecute 未在 AsyncTask 中调用(处理程序运行时异常)

转载 作者:IT老高 更新时间:2023-10-28 23:17:06 27 4
gpt4 key购买 nike

我有一个 AsyncTask 获取一些数据,然后用这些新数据更新 UI。几个月来它一直运行良好,但我最近添加了一个功能,当有新数据时显示通知。现在,当我的应用程序通过通知启动时,有时我会收到此异常并且未调用 onPostExecute

这是应用启动时发生的情况:

1) 展开 UI 并找到 View

2) 取消检查新数据的警报(通过AlarmManager)并重置警报。 (这样如果用户禁用警报,它会在他/她下次重新启动之前被取消。)

3) 启动AsyncTask。如果应用是通过通知启动的,请传入一点数据,然后取消通知。

我对可能导致此异常的原因感到困惑。似乎异常来自 AsyncTask 代码,所以我不确定如何修复它。

谢谢!

这是一个异常(exception):

I/My App(  501): doInBackground exiting
W/MessageQueue( 501): Handler{442ba140} sending message to a Handler on a dead thread
W/MessageQueue( 501): java.lang.RuntimeException: Handler{442ba140} sending message to a Handler on a dead thread
W/MessageQueue( 501): at android.os.MessageQueue.enqueueMessage(MessageQueue.java:179)
W/MessageQueue( 501): at android.os.Handler.sendMessageAtTime(Handler.java:457)
W/MessageQueue( 501): at android.os.Handler.sendMessageDelayed(Handler.java:430)
W/MessageQueue( 501): at android.os.Handler.sendMessage(Handler.java:367)
W/MessageQueue( 501): at android.os.Message.sendToTarget(Message.java:348)
W/MessageQueue( 501): at android.os.AsyncTask$3.done(AsyncTask.java:214)
W/MessageQueue( 501): at java.util.concurrent.FutureTask$Sync.innerSet(FutureTask.java:252)
W/MessageQueue( 501): at java.util.concurrent.FutureTask.set(FutureTask.java:112)
W/MessageQueue( 501): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:310)
W/MessageQueue( 501): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
W/MessageQueue( 501): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
W/MessageQueue( 501): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
W/MessageQueue( 501): at java.lang.Thread.run(Thread.java:1096)

编辑:这是我的主要 Activity (由通知打开的 Activity )中的 onCreate 方法。为了节省空间,我省略了一些 onClickListeners。我不认为它们应该有任何效果,因为它们所连接的按钮没有被按下。

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // Call the parent

setContentView(R.layout.main); // Create the UI from the XML file

// Find the UI elements
controls = (SlidingDrawer) findViewById(R.id.drawer); // Contains the
// buttons
// comic = (ImageView) findViewById(R.id.comic); // Displays the comic
subtitle = (TextView) findViewById(R.id.subtitleTxt); // Textbox for the
// subtitle
prevBtn = (Button) findViewById(R.id.prevBtn); // The previous button
nextBtn = (Button) findViewById(R.id.nextBtn); // The next button
randomBtn = (Button) findViewById(R.id.randomBtn); // The random button
fetchBtn = (Button) findViewById(R.id.comicFetchBtn); // The go to specific id button
mostRecentBtn = (Button) findViewById(R.id.mostRecentBtn); // The button to go to the most recent comic
comicNumberEdtTxt = (EditText) findViewById(R.id.comicNumberEdtTxt); // The text box to Zooming image view setup
zoomControl = new DynamicZoomControl();

zoomListener = new LongPressZoomListener(this);
zoomListener.setZoomControl(zoomControl);

zoomComic = (ImageZoomView) findViewById(R.id.zoomComic);
zoomComic.setZoomState(zoomControl.getZoomState());
zoomComic.setImage(BitmapFactory.decodeResource(getResources(), R.drawable.defaultlogo));
zoomComic.setOnTouchListener(zoomListener);

zoomControl.setAspectQuotient(zoomComic.getAspectQuotient());

resetZoomState();

// enter the new id
imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); // Used to hide the soft keyboard

Log.i(LOG_TAG, "beginning loading of first comic");
int notificationComicNumber = getIntent().getIntExtra("comic", -1);
Log.i(LOG_TAG, "comic number from intent: " + notificationComicNumber);
if (notificationComicNumber == -1) {
fetch = new MyFetcher(this, zoomComic, subtitle, controls, comicNumberEdtTxt, imm, zoomControl);
fetch.execute(MyFetcher.LAST_DISPLAYED_COMIC);
} else {
fetch = new MyFetcher(this, zoomComic, subtitle, controls, comicNumberEdtTxt, imm, zoomControl);
fetch.execute(notificationComicNumber);
((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).cancelAll();
}
Log.i(LOG_TAG, "ending loading of new comic");

Log.i(LOG_TAG, "first run checks beginning");
// Get SharedPreferences
prefs = getSharedPreferences("prefs", Context.MODE_PRIVATE);

// Check if this is the first run of the app for this version
if (prefs.getBoolean("firstRun-" + MAJOR_VERSION_NUMBER, true)) {
prefs.edit().putBoolean("firstRun-" + MAJOR_VERSION_NUMBER, false).commit();
firstRunVersionDialog();
}

// Check if this is the first run of the app
if (prefs.getBoolean("firstRun", true)) {
prefs.edit().putBoolean("firstRun", false).commit();
firstRunDialog();
}
Log.i(LOG_TAG, "First run checks done");

// OnClickListener s for the buttons omitted to save space

编辑 2:我一直在挖掘 Android 源代码,以追踪异常的来源。这是 HandlersendMessageAtTime 的第 456 和 457 行:

msg.target = this;
sent = queue.enqueueMessage(msg, uptimeMillis);

这是 MessageQueue 中的 enqueueMessage:

    final boolean enqueueMessage(Message msg, long when) {
if (msg.when != 0) {
throw new AndroidRuntimeException(msg
+ " This message is already in use.");
}
if (msg.target == null && !mQuitAllowed) {
throw new RuntimeException("Main thread not allowed to quit");
}
synchronized (this) {
if (mQuiting) {
RuntimeException e = new RuntimeException(
msg.target + " sending message to a Handler on a dead thread");
Log.w("MessageQueue", e.getMessage(), e);
return false;
} else if (msg.target == null) {
mQuiting = true;
}

msg.when = when;
//Log.d("MessageQueue", "Enqueing: " + msg);
Message p = mMessages;
if (p == null || when == 0 || when < p.when) {
msg.next = p;
mMessages = msg;
this.notify();
} else {
Message prev = null;
while (p != null && p.when <= when) {
prev = p;
p = p.next;
}
msg.next = prev.next;
prev.next = msg;
this.notify();
}
}
return true;
}

我对 mQuiting 是什么有点困惑,但看起来上一次 enqueueMessage 被称为 msg.target 为 null .

最佳答案

这是由于 Android 框架中的 AsyncTask 中的错误造成的。 AsyncTask.java 代码如下:

private static final InternalHandler sHandler = new InternalHandler();

它希望在主线程上初始化它,但这不能保证,因为它会在恰好导致类运行其静态初始化程序的任何线程上初始化。我在 Handler 引用工作线程时重现了这个问题。

导致这种情况发生的常见模式是使用 IntentService 类。 C2DM 示例代码执行此操作。

一个简单的解决方法是将以下代码添加到应用程序的 onCreate 方法中:

Class.forName("android.os.AsyncTask");

这将强制 AsyncTask 在主线程中初始化。我在 android 错误数据库中提交了一个错误。见 http://code.google.com/p/android/issues/detail?id=20915 .

关于android - onPostExecute 未在 AsyncTask 中调用(处理程序运行时异常),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4280330/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com