3

I think it is due to low memory if I set the app background. The log is like below:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.qingdaonews.bus/com.qingdaonews.activity.RealTime}: 
java.lang.IllegalArgumentException: Wrong state class, expecting View State but received class android.view.View$BaseSavedState instead. This usually happens when two views of different type have the same id in the same hierarchy. This view's id is id/myviewpager. Make sure other views do not use the same id.
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2266)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2316)
    at android.app.ActivityThread.access$600(ActivityThread.java:150)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1298)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:213)
    at android.app.ActivityThread.main(ActivityThread.java:5225)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:525)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:741)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
    at dalvik.system.NativeStart.main(Native Method)





It looks like due to the same id of a view.In fact ,the id 'myviewpager' only appear once in the xml file and the problem only occur when the app is reopen from background.


And my MainActivity has one fragment which can be replaced in it.I use getSupportFragmentManager().beginTransaction().replace(R.id.content_frame, fragment).commit(); when I start the activity.
Without super method of 'savedInstanceState',I did not use something else.

fadden
  • 51,356
  • 5
  • 116
  • 166
Marshal Chen
  • 1,985
  • 4
  • 24
  • 35
  • Check how you recreate objects from `Bundle savedInstanceState`. Maybe you're calling `super(savedInstanceState)` when `savedInstanceState` is not `null`, thus creating your `View` once, and then manually try to add `View` with the same id upon inflating your layout and initializing things. Anyway, the are many things to guess if you do not wish to disclose your code to us. – Drew Mar 19 '14 at 07:46
  • @Drew Thank you very much.In my savedInstanceState,I only use " super.onSaveInstanceState(outState);" and not manually add any views.The MainActivity of my app has one but only one fragment which can be replaced to show some info.Is these fragment will cause some problem? Thank you very much! – Marshal Chen Mar 19 '14 at 07:58
  • not only this method, check `onCreate(Bundle savedInstanceState)`, that's where the magic of recreation happens during your Activity's lifecycle – Drew Mar 19 '14 at 08:01
  • @Drew Without super method of 'savedInstanceState',I did not use something else. 'onCreate(Bundle savedInstanceState)','onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)' – Marshal Chen Mar 19 '14 at 08:29
  • Can you write more code or specify where the myviewpager is located? Without layouts' XML and some initialized code it is hard to guess what could be the cause. I provided one of the common issues. – Drew Mar 19 '14 at 09:00
  • The fragment1 is in the MainActivity and there is a click method in the fragment1 which can start activity2, and the myviewpager is a ViewPager in the activity. – Marshal Chen Mar 19 '14 at 09:05
  • @Drew And sometimes in some other devices, the problem may be cause in the fragment2 of MainActivity which also can be switched – Marshal Chen Mar 19 '14 at 09:07

2 Answers2

3

The cause is that your Fragment gets re-added. Your code looks like this:

protected void onCreate(Bundle savedInstanceState){
    super(savedInstanceState);        
    ///...
    getSupportFragmentManager().beginTransaction()
        .replace(R.id.content_frame, fragment).commit();
}

Associated FragmentManager gets restored if savedInstanceState != null via a call to super(savedInstanceState), and all the commited fragments get restored too. Instead, check if your fragment is already added, and add it only if not:

public class MyActivity extends Activity{

    private MyFragment myFragment;//extends Fragment

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //your stuff
        FragmentManager fm = getFragmentManager();
        myFragment = (MyFragment) fm.findFragmentByTag(MyFragment.TAG);
        if(myFragment == null){
            myFragment = new MyFragment();
            fm.beginTransaction()
                .add(R.id.content_frame, myFragment, MyFragment.TAG)
                .commit();
         }
        //other stuff
    }
}

And in your MyFragment, TAG is: public static final String TAG = MyFragment.class.getSimpleName();

As for me, I found it is a nice practice to add Fragments with TAG parameter provided.

Drew
  • 3,307
  • 22
  • 33
  • Thank you very much and I'll try it. But I wonder why the replace method could re-added the fragment? – Marshal Chen Mar 19 '14 at 08:49
  • Your application flow is not yet clear from what you describe. So, I can not say anything based on the supplied info, as my assumptions could be wrong. I suggest you to use the approach provided in the answer and **double check** all of your existing elements' identifiers. – Drew Mar 19 '14 at 09:32
  • @MarshalChen If nothing else, provide only the part of code in your Activitiy responsible for creation of ViewPager. – Drew Mar 19 '14 at 09:39
1

We had this problem with low memory conditions (Dev settings -> "Do not keep activities" set) and custom views crashing while trying to do a restore of custom vies (overriding View.onRestoreInstanceState()) As specified here. Views had no duplicate IDs.

A bug in the way the fragment was being restored (that contained the custom view), caused it to add different views at runtime while restoring, than was added when saving the instance state. (In our case a read write version of the custom view was added initially, but restoring the fragment added the read-only version of the view.)

I suspect Android then tries to set the state of the read-write views on the read-only views, and this breaks things.

This was observed on Android 4.4.4 but not Android 6.0.1

Exception we got was:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.package.name/com.package.name.VisitActivity}: java.lang.IllegalArgumentException: Wrong state class, expecting View State but received class com.package.name.view.CustomView$CustomViewState instead. This usually happens when two views of different type have the same id in the same hierarchy. This view's id is id/0x465127ed. Make sure other views do not use the same id.
  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2413)
  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2471)
  at android.app.ActivityThread.access$900(ActivityThread.java:175)
  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1308)
  at android.os.Handler.dispatchMessage(Handler.java:102)
  at android.os.Looper.loop(Looper.java:146)
  at android.app.ActivityThread.main(ActivityThread.java:5602)
  at java.lang.reflect.Method.invokeNative(Native Method)
  at java.lang.reflect.Method.invoke(Method.java:515)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
  at dalvik.system.NativeStart.main(Native Method)
Diederik
  • 5,536
  • 3
  • 44
  • 60