I have spent hours trying to fix an app crash and I think it deserves a question:
The Exception:
java.lang.IllegalStateException: View android.widget.LinearLayout{41a97eb8 V.E..... ......ID 0,0-540,105 #7f0b020d app:id/toast_layout_root} has already been added to the window manager.
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:223)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
at android.widget.Toast$TN.handleShow(Toast.java:402)
at android.widget.Toast$TN$1.run(Toast.java:310)
at android.os.Handler.handleCallback(Handler.java:730)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5136)
at java.lang.reflect.Method.invokeNative(Method.java)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(NativeStart.java)
The Code:
I have a custom toast following this guide
I defined the custom toast as ToastMessageBar.java
and the constructor looks like this:
public ToastMessageBar(Activity activity) {
LayoutInflater inflater = activity.getLayoutInflater;
mToastLayout = inflater.inflate(R.layout.toast_layout,
(ViewGroup) activity.findViewById(R.id.toast_layout_root));
mMessageView = (TextView) mToastLayout.findViewById(R.id.toast_message);
mSubtitleView = (TextView) mToastLayout.findViewById(R.id.toast_subtitle);
}
and the way I show a toast message is following:
private void showMessage(MessageType type, String message, String subtitle) {
int duration = Toast.LENGTH_SHORT;
if (mToastLayout != null) {
int colorId;
switch (type) {
case Warning:
colorId = R.color.warning_bar_color;
duration = Toast.LENGTH_SHORT;
break;
case Error:
colorId = R.color.error_bar_color;
break;
default:
colorId = R.color.info_bar_color;
break;
}
mToastLayout.setBackgroundColor(
MyApp.getContext().getResources().getColor(colorId));
if (subtitle == null) {
mMessageView.setVisibility(View.GONE);
mSubtitleView.setText(message);
} else {
mMessageView.setVisibility(View.VISIBLE);
mMessageView.setText(message);
mSubtitleView.setText(subtitle);
}
}
Utils.showToast(mToastLayout, message, duration);
}
public static void showToast(View layout, String message, int duration) {
if (layout != null) {
Toast toast = new Toast(MyApp.getContext());
toast.setGravity(Gravity.TOP|Gravity.FILL_HORIZONTAL, 0, 0);
toast.setDuration(duration);
toast.setView(layout);
toast.show();
return;
}
Toast.makeText(MyApp.getContext(), message, Toast.LENGTH_LONG).show();
}
In MyBaseActivity.onCreate()
I define the ToastMessageBar:
mMessageBar = new ToastMessageBar(this);
In this way, I can use showMessage()
in all the activities that inherits MyBaseActivity
.
It seems the exception happens when I call toast.show();
but it does not happen all the time (only rare cases) I don't know what caused the exception still.
First off- when you're asking for help on an exception, always give us the full stack trace.
You're screwing up with your inflation and Toast usage. When you use the layout the first time, you're cool. The second time, it already has a parent (the Toast), so it will throw an error when you try to add it to the toast via setView. You either need to inflate a new copy each Toast, or remove it from the old Toast before adding it to the new one.
You'd better set a new view every time you want to show the Toast.
In Toast.java handleHide() function. It says:
// note: checking parent() just to make sure the view has
// been added... i have seen cases where we get here when
// the view isn't yet added, so let's try not to crash.
if (mView.getParent() != null) {
if (localLOGV) Log.v(TAG, "REMOVE! " + mView + " in " + this);
mWM.removeView(mView);
}
And in Toast.java handleShow() function
if (mView.getParent() != null) {
if (localLOGV) Log.v(TAG, "REMOVE! " + mView + " in " + this);
mWM.removeView(mView);
}
if (localLOGV) Log.v(TAG, "ADD! " + mView + " in " + this);
mWM.addView(mView, mParams);
May be when the last view been added but don't have a parent yet. A new view comes. Then it throw IllegalStateException
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With