Question

I want to show a Toast right after the user clicks on a CheckBoxPreference in my PreferenceActivity.

myCheckBox.setOnPreferenceClickListener(new OnPreferenceClickListener() {
            @Override
            public boolean onPreferenceClick(Preference preference) {
                Toast.makeText(Prefs.this,
                        "test",
                        Toast.LENGTH_SHORT).show();
                doSomething();
                return false;
            }
        });

I also tried to put the Toast into the doSomething() method, but it's always shown after the whole method is processed. I tried getBaseContext() instead of Prefs.this, but it didn't help. Any idea why the Toast doesn't show up at once and how to make it do so?

Was it helpful?

Solution

This is happening because the onPreferenceClick listener is running in the UI thread. This thread is also the same as the one that handles displaying the Toast. Toast#show only pushes a message onto the message queue that will then run code to make the Toast display. That queue won't be processed until after your onPreferenceClick handler is completely finished.

You can try:

myCheckBox.setOnPreferenceClickListener(new OnPreferenceClickListener() {
            @Override
            public boolean onPreferenceClick(Preference preference) {
                Toast.makeText(Prefs.this,
                        "test",
                        Toast.LENGTH_SHORT).show();

                Prefs.this.runOnUiThread(new Runnable() {
                    @Override
                        public void run() {
                            doSomething();
                        }
                    });
                return false;
            }
    });

This will cause the Toast to post to the message queue then your doSomething will also be posted to the queue after the toast. The downside to this is that there could be UI messages that will be handled before doSomething is called. Also, if doSomething is long running it will monopolize your UI thread and could cause a possible ANR force close. You may want to think about running doSomething in an AsyncTask if it takes more than 150ms or so.

OTHER TIPS

My solution is use broadcast, and make a receiver registered in android manifest.

in AndroidManifest:

    <receiver android:name=".MyReceiver" >
        <intent-filter >
            <action android:name="showtoast" />
        </intent-filter>
    </receiver>

sending broadcast:

public static void BroadcastMessage(Context context, Bundle extra)
{
    Intent intent = new Intent();
    intent.setPackage(context.getPackageName());
    intent.setAction("showtoast");
    if (extra != null)
        intent.putExtras(extra);
    context.sendBroadcast(intent);
}

receiver like below:

public class MyReceiver extends BroadcastReceiver {

    public void onReceive(Context context, Intent intent) {
        Bundle bundle = intent.getExtras();
        if ("showtoast".equalsIgnoreCase(intent.getAction()) && (bundle != null)
        {
            String title = bundle.getString("title", "");

            View view;
            TextView mTextView;
            LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(R.layout.my_toast_layout, null);
            mTextView = (TextView) view.findViewById(R.id.tv_title);
            mTextView.setText(title);

            Toast toast = new Toast(context.getApplicationContext());
            toast.setGravity(Gravity.CENTER, 0, 0);
            toast.setView(view);
            toast.setDuration(Toast.LENGTH_LONG);
            toast.show();
        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top