0

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

    }

}
click_whir
  • 427
  • 5
  • 19

2 Answers2

0

You are passing application context to your Toast, the toast lifecycle will tie with context of your application. You should pass in your current activity.

toast = Toast.makeText(this, "my error message", Toast.LENGTH_SHORT);

toast.show();

Ethan
  • 1,616
  • 14
  • 8
  • I thought it was desirable to be tied to the application context? As the activity may exit after presenting toast. `this` is not the Activity, as this Toast is shown in the ResultReceiver class. I attempted to move the ResultReciever contents to another method where I could access `this`, but the outcome is the same. The Toast appears and never goes away. – click_whir Jun 01 '13 at 23:40
  • I see that the Toast is under your inner class MyServiceReceiver, you do not need to move your code out to use this, can use Toast.makeText(MyActivity.this, "my error message", Toast.LENGTH_SHORT).show(). More importantly make sure that your toast is not called multiple times. Let me know if it works for you. – Ethan Jun 02 '13 at 10:25
  • Thanks, I still have a thing or two to learn about Java. Using the Activity context is still not fixing the issue. The ResultReceiver is being called from an IntentService, so is on a non-UI thread, and [I see now that the Toasts must be made from UI thread](http://stackoverflow.com/questions/12407910/android-toast-from-intentservice-remains-on-screen-for-ever?lq=1). – click_whir Jun 03 '13 at 18:18
0

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.

Community
  • 1
  • 1
click_whir
  • 427
  • 5
  • 19