Note that there are some explanatory texts on larger screens.

plurals
  1. POCalling Looper more than once causes "sending message to a Handler on a dead thread"
    primarykey
    data
    text
    <p>I am using an Executor [fixed thread pool] with my own ThreadFactory that adds a Looper:</p> <pre><code>Handler HANDLER = new Handler(); Executor THREADS = Executors.newFixedThreadPool(THREAD_POOL_SIZE, new ThreadFactory() { @Override public Thread newThread(Runnable runnable) { return new MyThread(new Runnable() { @Override public void run() { Looper.prepare(); runnable.run(); } }); } }); private static class MyHandler extends Handler { public boolean fail; public void handleMessage(Message msg) { switch(msg.what) { case 1: this.fail = msg.arg1 == 1; Looper.myLooper().quit(); break; } } } } </code></pre> <p>I am running a thread that makes network requests but if the network fails I would like a dialog message to be displayed to the user. This process is rather involving since it requires making AND displaying the request in the UI thread. I can wait for the user's response to the dialog by simply adding a Loop to the network thread and wait for a message to be send from the UI thread. This allows me to encapsulate the network requests in a while(tryAgain) thread. All works well except when the Looper.loop() method is called the second time (after a second network error dialog is displayed) and a message is sent by the dialog (in the UI thread) to the network thread's handler:</p> <pre><code>THREADS.execute(new Runnable() { private MyHandler myHandler = new MyHandler(); @Override public void run() { boolean tryAgain = true; while(tryAgain) { try { switch(request) { [Handle network requests] } tryAgain = false; } catch(IOException e) { // The network is unavailable. Ask the user if we should try again. e.printStackTrace(); } finally { if(tryAgain) { HANDLER.post(new Runnable() { // The UI thread @Override public void run() { theAlertDialog.show(); } }); // Wait for the results from the dialog which lives in the UI thread. Looper.loop(); // At this point the dialog has informed us of our answer. tryAgain = !myHandler.fail; } } } } }); </code></pre> <p>In the AlertDialog instance is an OnClickListener:</p> <pre><code>DialogInterface.OnClickListener myOnclickListener = new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { Message msg = myHandler.obtainMessage(1); msg.setTarget(this.handler); msg.sendToTarget(); } } </code></pre> <p>I've checked that the thread is still active with <code>handler.getLooper().getThread().isAlive()</code> which always returns true but it still gives me "sending message to a Handler on a dead thread". How is it that the Message/Handler has decided that the thread is dead? Shouldn't it rely on the .isAlive() method? In the end I am trying to avoid replicating the thread management build into the Android OS :-)</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload