Ich habe eine AsyncTask
, die einige Daten abruft und dann die Benutzeroberfläche mit diesen neuen Daten aktualisiert. Es funktioniert seit Monaten einwandfrei, aber ich habe kürzlich eine Funktion hinzugefügt, die eine Benachrichtigung anzeigt, wenn neue Daten vorhanden sind. Jetzt, wenn meine App durch die Benachrichtigung gestartet wird, bekomme ich manchmal diese Ausnahme und onPostExecute
wird nicht aufgerufen.onPostExecute nicht in AsyncTask (Handler-Laufzeitausnahme)
Dies ist, was passiert, wenn die App gestartet wird:
1) die Benutzeroberfläche erweitern und den Alarm (durch AlarmManager
), die für neue Daten und stellen Sie den Alarm überprüft Abbrechen Ansichten
2) finden. (Wenn der Benutzer den Alarm deaktiviert, wird er abgebrochen, bevor er das nächste Mal neu gestartet wird.)
3) Starten Sie die AsyncTask
. Wenn die App von der Benachrichtigung gestartet wurde, geben Sie ein wenig Daten ein und brechen Sie dann die Benachrichtigung ab.
Ich stecke auf, was könnte diese Ausnahme verursachen. Es scheint, dass die Ausnahme von der AsyncTask
Code ist, also bin ich mir nicht sicher, wie ich es beheben kann.
Danke! Hier
ist die Ausnahme:
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)
EDIT: Hier ist meine onCreate
Methode in meiner Haupttätigkeit (die man durch die Benachrichtigung geöffnet). Es gibt einige onClickListeners
, die ich weggelassen habe, um Platz zu sparen. Ich denke nicht, dass sie irgendeinen Effekt haben sollten, da die Knöpfe, an denen sie befestigt sind, nicht gedrückt werden.
@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
BEARBEITEN 2: Ich habe durch Android-Quellcode gegraben, wo die Ausnahme herkommt. Dies ist Linien 456 und 457 von sendMessageAtTime
in Handler
:
msg.target = this;
sent = queue.enqueueMessage(msg, uptimeMillis);
Und das ist enqueueMessage
von MessageQueue
:
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;
}
ich ein wenig verwirrt darüber bin, was mQuiting
ist, aber es sieht aus wie die vorherige Zeit enqueueMessage
hieß msg.target
war Null.
Der Thread, der Ihre AsyncTask erstellt hat, muss beendet worden sein. Wie erstellst du deine AsyncTask? –
Ich habe meine Frage mit dem Code aktualisiert. Ich kann nicht sehen, wie die Aktivität beendet wurde, wenn ich den Ladebildschirm noch sehen kann. – Computerish
Wir müssen mehr Code sehen. – Falmarri