Android: IllegalStateException if compiled with targetSdkVersion=21 5.0.1


#1

Hi

Up to now I built the Application with targetSdkVersion=19. But when I switch to targetSdkVersion=21 the app throws following exception when inflating a fragment from xml which contains a ChartFragment:

02-08 15:09:57.785: E/AndroidRuntime(23263): FATAL EXCEPTION: main
02-08 15:09:57.785: E/AndroidRuntime(23263): Process: com.test, PID: 23263
02-08 15:09:57.785: E/AndroidRuntime(23263): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.test/com.test.ui.HistoryActivity}: android.view.InflateException: Binary XML file line #6: Error inflating class fragment
02-08 15:09:57.785: E/AndroidRuntime(23263): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2298)
02-08 15:09:57.785: E/AndroidRuntime(23263): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
02-08 15:09:57.785: E/AndroidRuntime(23263): at android.app.ActivityThread.access$800(ActivityThread.java:144)
02-08 15:09:57.785: E/AndroidRuntime(23263): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
02-08 15:09:57.785: E/AndroidRuntime(23263): at android.os.Handler.dispatchMessage(Handler.java:102)
02-08 15:09:57.785: E/AndroidRuntime(23263): at android.os.Looper.loop(Looper.java:135)
02-08 15:09:57.785: E/AndroidRuntime(23263): at android.app.ActivityThread.main(ActivityThread.java:5221)
02-08 15:09:57.785: E/AndroidRuntime(23263): at java.lang.reflect.Method.invoke(Native Method)
02-08 15:09:57.785: E/AndroidRuntime(23263): at java.lang.reflect.Method.invoke(Method.java:372)
02-08 15:09:57.785: E/AndroidRuntime(23263): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
02-08 15:09:57.785: E/AndroidRuntime(23263): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
02-08 15:09:57.785: E/AndroidRuntime(23263): Caused by: android.view.InflateException: Binary XML file line #6: Error inflating class fragment
02-08 15:09:57.785: E/AndroidRuntime(23263): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:763)
02-08 15:09:57.785: E/AndroidRuntime(23263): at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
02-08 15:09:57.785: E/AndroidRuntime(23263): at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
02-08 15:09:57.785: E/AndroidRuntime(23263): at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
02-08 15:09:57.785: E/AndroidRuntime(23263): at com.test.ui.HistoryFragment.onCreateView(HistoryFragment.java:261)
02-08 15:09:57.785: E/AndroidRuntime(23263): at android.app.Fragment.performCreateView(Fragment.java:2053)
02-08 15:09:57.785: E/AndroidRuntime(23263): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:894)
02-08 15:09:57.785: E/AndroidRuntime(23263): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
02-08 15:09:57.785: E/AndroidRuntime(23263): at android.app.BackStackRecord.run(BackStackRecord.java:833)
02-08 15:09:57.785: E/AndroidRuntime(23263): at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1452)
02-08 15:09:57.785: E/AndroidRuntime(23263): at android.app.Activity.performStart(Activity.java:5948)
02-08 15:09:57.785: E/AndroidRuntime(23263): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2261)
02-08 15:09:57.785: E/AndroidRuntime(23263): ... 10 more
02-08 15:09:57.785: E/AndroidRuntime(23263): Caused by: java.lang.IllegalStateException: Can't retain fragements that are nested in other fragments
02-08 15:09:57.785: E/AndroidRuntime(23263): at android.app.Fragment.setRetainInstance(Fragment.java:959)
02-08 15:09:57.785: E/AndroidRuntime(23263): at com.shinobicontrols.charts.ChartFragmentBase.onCreate(SourceFile:45)
02-08 15:09:57.785: E/AndroidRuntime(23263): at com.shinobicontrols.charts.ChartFragment.onCreate(SourceFile:45)
02-08 15:09:57.785: E/AndroidRuntime(23263): at android.app.Fragment.performCreate(Fragment.java:2031)
02-08 15:09:57.785: E/AndroidRuntime(23263): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:863)
02-08 15:09:57.785: E/AndroidRuntime(23263): at android.app.FragmentManagerImpl.onCreateView(FragmentManager.java:2139)
02-08 15:09:57.785: E/AndroidRuntime(23263): at android.view.LayoutInflater$FactoryMerger.onCreateView(LayoutInflater.java:177)
02-08 15:09:57.785: E/AndroidRuntime(23263): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:733)
02-08 15:09:57.785: E/AndroidRuntime(23263): ... 21 more

I’ll continue using 19 where it works. But I wanted to let you know, that something changed with handling retained fragments inside fragments with the API 21 sdk.

Kind Regards

Urs Grob


#2

Hi Urs,

Thanks very much for posting this. Yes, it does seem that when compiling with API 21 Android is more strict about nested fragments.

For the benefit of anyone reading this it’s important to realise that our ChartFragment retains its instance across configuration changes. Ultimately this means you don’t have to worry about saving the chart’s state across such changes but limits you to not being able to put ChartFragments inside other Fragments.

If this is required you will want to create your own ‘ChartFragment’ - a Fragment that contains a ChartView. You have to make sure you forward any lifecycle calls from the Fragment to the ChartView, namely onPause and onResume, otherwise you’ll get a crash when you navigate away and back to your app. As you cannot call setRetainInstance(true) you will also be responsible for persisting any state across configuration changes (but depending on your use case this may not be that big a thing).

Android only allows nested fragments when they are created in code, not XML, and as far as I understand it both the outer and inner fragments have to be created in code.

Kind regards,

Patrick