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

247 views Asked by At

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.

1

There are 1 answers

0
Mouaad Abdelghafour AITALI On BEST ANSWER

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);