membersound
membersound

Reputation: 86747

How to show AlertDialog from ScheduledExecutor?

I want to set up a scheduler and show a popup after a predefined time.

In the following example, the Log "scheduled alert" is printed once, but the alert dialog is never shown.

public class MainActivity extends AppCompatActivity {

        @Override
        protected void onCreate(Bundle savedInstanceState) {
             //...
             initAlert(this);
        }

        private void initAlert(Activity activity) {
            final ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
            executor.schedule(new Runnable() {
                @Override
                public void run() {
                  Log.i("app", "scheduled alert");

                  new AlertDialog.Builder(activity)
                    .setTitle("test")
                    .setMessage("lorep")
                    .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            Log.i("app", "ok clicked");
                        }
                    })
                    .setIcon(android.R.drawable.ic_dialog_alert)
                    .create()
                    .show();
                }
            }, 10, TimeUnit.SECONDS);
        }
}

The initialization is inside the main activity.

Why is the dialog not shown?

If I add a button to my view, and link the alert dialog explicit to that button click, it works. So the dialog code in general should be fine.

Upvotes: 0

Views: 300

Answers (2)

lelloman
lelloman

Reputation: 14173

the problem of your code is that you're trying to show the Dialog not from the UI thread.

if all you need is to delay the display of the dialog by 10 seconds, and that would be it, you can use a Handler

private final Handler handler = new Handler();
private final Runnable showDialogRunnable = new Runnable() {
    @Override
    public void run() {
        new AlertDialog.Builder(MainActivity.this)
                .setTitle("test")
                .setMessage("lorep")
                .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        Log.i("app", "ok clicked");
                    }
                })
                .setIcon(android.R.drawable.ic_dialog_alert)
                .create()
                .show();
    }
};

and post it

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    handler.postDelayed(showDialogRunnable, 10000);
...

if you want to cancel the scheduled execution you can call

handler.removeCallbacks(showDialogRunnable);

the thing is, if you don't pass Looper in the constuctor, the Handler with use the Looper associated with the Thread where the constructor is being called, in this case it would be the UI thread

update

if you want to keep your activity cleaner, you could create another class that implements that Runnable, for example

public class AlertDialogShower implements Runnable {
    private Context context;

    public AlertDialogShower(Context context){
        this.context = context;
    }

    @Override
    public void run() {
        new AlertDialog.Builder(context)
                .setTitle("test")
                .setMessage("lorep")
                .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        Log.i("app", "ok clicked");
                    }
                })
                .setIcon(android.R.drawable.ic_dialog_alert)
                .create()
                .show();
    }
}

and then instantiate it in your activity

private final Runnable showDialogRunnable = new AlertDialogShower(this);

Upvotes: 1

Piotr Golinski
Piotr Golinski

Reputation: 1000

private void initAlert() {
    final ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
    executor.schedule(new Runnable() {
        @Override
        public void run() {
            Log.i("app", "scheduled alert");
            YourActivity.this.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    new AlertDialog.Builder(this)
                            .setTitle("test")
                            .setMessage("lorep")
                            .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, int id) {
                                    Log.i("app", "ok clicked");
                                }
                            })
                            .setIcon(android.R.drawable.ic_dialog_alert)
                            .create()
                            .show();
                }
            });

        }
    }, 10, TimeUnit.SECONDS);
}

Upvotes: 1

Related Questions