Search code examples
androidtimertaskandroid-timer

How to display a dialog inside TimerTask's run() after calling Looper.prepare();?


In activity's onCreate(), I arm a TimerTask that should display a dialog after 10 secs :

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

     TimerTask timerTask = new TimerTask() {

        @Override
        public void run() {
            
            Looper.prepare();
            Toast.makeText(getApplicationContext(), "Test", Toast.LENGTH_LONG).show();
            
            Log.i(this.getClass().getName(), "Dialog should be displayed...");
            new AlertDialog.Builder(MainActivity.this)
                    .setTitle("TEST")
                    .setMessage("This is a test")
                    .show();
            }
        };
        Timer timer = new Timer();
        timer.schedule(timerTask, 10000);
}

When this activity is created, the Toast is displayed after 10 secs, but not the dialog. Any idea why ?

I'm compiling using Android SDK 33.


Solution

  • If you run your code like this, your app will crash with the following error :

    java.lang.IllegalStateException: Method handleLifecycleEvent must be called on the main thread
    

    The error you're seeing is because you're calling Looper.prepare() and creating a AlertDialog on a background thread. This is not allowed because AlertDialog must be created on the main thread.

    To fix this, you can move the code that creates the AlertDialog inside the runOnUiThread method. This will ensure that the code is executed on the main thread. Here's how your code would look like with this change:

    TimerTask timerTask = new TimerTask() {
    
                @Override
                public void run() {
    
                    Looper.prepare();
                    Toast.makeText(getApplicationContext(), "Test", Toast.LENGTH_LONG).show();
    
                    Log.i(this.getClass().getName(), "Dialog should be displayed...");
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            new AlertDialog.Builder(MainActivity.this)
                                    .setTitle("TEST")
                                    .setMessage("This is a test")
                                    .show();
                        }
                    });
    
                }
            };
            Timer timer = new Timer();
            timer.schedule(timerTask, 2000);