Search code examples
androidandroid-fragmentstoastfragmenttransaction

Toasts never clear when I swap fragments


I provide user feedback via a Toast prior to switching Fragments in my app. Once the Toast appears, it never clears. Exiting the Activity or killing the whole thing is the only way to clear the Toast.

I have attempted to hold a reference to the Toast and call cancel() after committing the FragmentTransaction, but when I do that the Toast never appears at all.

I have added logging and am certain that the Toast is only being displayed once, not in a loop or repeatedly. The app is still responsive otherwise, and not hung. When I exit the app the Toast clears thanks to the cancel() in onStop().

public final class MyActivity extends SherlockFragmentActivity {

    Toast toast = null;

    //...

    @Override
    protected void onStop () {
        if (toast != null) toast.cancel();
        toast = null;
        super.onStop();
    }

    //...

    private final class MyServiceReceiver extends ResultReceiver {

        public MyServiceReceiver(Handler handler) {
            super(handler);
        }

        @Override
        protected void onReceiveResult(int resultCode, Bundle resultData) {
            if (resultCode == MY_ERROR_CODE) {
                toast = Toast.makeText(getApplicationContext(), "my error message", Toast.LENGTH_SHORT);
                toast.show();

                FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
                ft.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out,
                            android.R.anim.fade_in, android.R.anim.fade_out);
                ft.replace(R.id.main_layout, new MyFragment());
                ft.commit();

                //if (toast != null) toast.cancel();
                //toast = null;
            }
        }

    }

}

Solution

  • The problem here is that an IntentService is calling the ResultReceiver, so the Toast is being created off the UI thread. See this post.

    To solve I create a handler for the Activity and make the Toasts in there. As a bonus it appears I don't have to manage a reference to the Toast and clear on Activity.onStop.