6

I have a fragment which adds an option to the option menu. When this option is clicked a dialog fragment opens. The dialog has the original fragment set to its target fragment. If no orientation change happens while the dialog fragment is open the target fragment is as expected but after orientation change the target fragment is set to the dialog fragment itself instead of the fragment which was set previously. As a result I get a classCastException when trying to cast the target fragment to the fragment which was set as the target fragment. I need to get the target fragment in my dialog because it implements a callback (OnStartOrRestartLoader). I've been trying to solve this issue for over a week and would really appreciate if somebody could point me in the right direction. Since this is my first question here I apologize if I've excluded some necessary information or if this is not an appropriate question here.

In the fragment (VirsārstsFragment) which implements OnStartOrRestartLoader I create the dialog as follows:

FragmentManager fm = getChildFragmentManager();
SearchDialogFragment dialog = new SearchDialogFragment();
dialog.show(fm, "searchDialog");
dialog.setTargetFragment(this, DIALOGFRAGMENT);

Then in the SearchDialogFragment I do the following to set the callback:

OnStartOrRestartLoader callback = (OnStartOrRestartLoader) getTargetFragment();

Logcat:

08-25 12:15:55.087: E/AndroidRuntime(10057): FATAL EXCEPTION: main
08-25 12:15:55.087: E/AndroidRuntime(10057): Process: com.example, PID: 10057
08-25 12:15:55.087: E/AndroidRuntime(10057): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example/com.example.MainActivity}: java.lang.ClassCastException: com.example.SearchDialogFragment cannot be cast to com.example.OnStartOrRestartLoader
08-25 12:15:55.087: E/AndroidRuntime(10057):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2224)
08-25 12:15:55.087: E/AndroidRuntime(10057):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2273)
08-25 12:15:55.087: E/AndroidRuntime(10057):    at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3759)
08-25 12:15:55.087: E/AndroidRuntime(10057):    at android.app.ActivityThread.access$900(ActivityThread.java:141)
08-25 12:15:55.087: E/AndroidRuntime(10057):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1208)
08-25 12:15:55.087: E/AndroidRuntime(10057):    at android.os.Handler.dispatchMessage(Handler.java:102)
08-25 12:15:55.087: E/AndroidRuntime(10057):    at android.os.Looper.loop(Looper.java:136)
08-25 12:15:55.087: E/AndroidRuntime(10057):    at android.app.ActivityThread.main(ActivityThread.java:5052)
08-25 12:15:55.087: E/AndroidRuntime(10057):    at java.lang.reflect.Method.invokeNative(Native Method)
08-25 12:15:55.087: E/AndroidRuntime(10057):    at java.lang.reflect.Method.invoke(Method.java:515)
08-25 12:15:55.087: E/AndroidRuntime(10057):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
08-25 12:15:55.087: E/AndroidRuntime(10057):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
08-25 12:15:55.087: E/AndroidRuntime(10057):    at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132)
08-25 12:15:55.087: E/AndroidRuntime(10057):    at dalvik.system.NativeStart.main(Native Method)
08-25 12:15:55.087: E/AndroidRuntime(10057): Caused by: java.lang.ClassCastException: com.example.SearchDialogFragment cannot be cast to com.example.OnStartOrRestartLoader
08-25 12:15:55.087: E/AndroidRuntime(10057):    at com.example.SearchDialogFragment.onCreateDialog(SearchDialogFragment.java:59)
08-25 12:15:55.087: E/AndroidRuntime(10057):    at android.support.v4.app.DialogFragment.getLayoutInflater(DialogFragment.java:307)
08-25 12:15:55.087: E/AndroidRuntime(10057):    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:942)
08-25 12:15:55.087: E/AndroidRuntime(10057):    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1121)
08-25 12:15:55.087: E/AndroidRuntime(10057):    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1103)
08-25 12:15:55.087: E/AndroidRuntime(10057):    at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1901)
08-25 12:15:55.087: E/AndroidRuntime(10057):    at android.support.v4.app.Fragment.performActivityCreated(Fragment.java:1518)
08-25 12:15:55.087: E/AndroidRuntime(10057):    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:962)
08-25 12:15:55.087: E/AndroidRuntime(10057):    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1121)
08-25 12:15:55.087: E/AndroidRuntime(10057):    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1103)
08-25 12:15:55.087: E/AndroidRuntime(10057):    at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1901)
08-25 12:15:55.087: E/AndroidRuntime(10057):    at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:567)
08-25 12:15:55.087: E/AndroidRuntime(10057):    at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1171)
08-25 12:15:55.087: E/AndroidRuntime(10057):    at android.app.Activity.performStart(Activity.java:5322)
08-25 12:15:55.087: E/AndroidRuntime(10057):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2187)
08-25 12:15:55.087: E/AndroidRuntime(10057):    ... 13 more
  • can you post more code – Blackbelt Aug 25 '14 at 09:30
  • Does your UI change on orientation change? I mean do you have a different UI to be shown for each orientation? – pvn Aug 25 '14 at 09:42
  • I don't get it. `getTargetFragment()` returns a `Fragment` and you are trying to cast it to `OnStartOrRestartLoader`. The exception is very clear. What are you trying to do? – Simon Aug 25 '14 at 09:51
  • @Simon what you mentioned is true now that I think of it, but the same problem persists even if I try to cast to VirsārstsFragment which extendes Fragment. I found a solution by using getParentFragment instead of getTargetFragment. – Dāvis Sparinskis Aug 25 '14 at 13:50
  • @pvn the same UI. I add spinners and textviews programatically and want to retain their contents after rotation(that's working) when I click the positive button I need to restart the cursorLoader with new parameters in the parent fragment (works only if no orientation change). – Dāvis Sparinskis Aug 25 '14 at 14:01

4 Answers4

5

setTargetFragment should not be used to establish a relationship between parent/child fragments. It should only be used to link sibling fragments (i.e. those that exist within the same FragmentManager).

The reason it doesn't work between parent/child fragments is a fragment's target is saved and restored as an index into its own FragmentManager. So everything will be hunky dory until the framework restores an Activity after, for example, an orientation change. At that point the FragmentManager will look for the target fragment within itself instead of the parent FragmentManager.

Joeleski
  • 459
  • 4
  • 11
3

I don't still understand why exactly getTargetFragment() didn't work for me, but replacing it with getParentFragment() solved my issue.

Eric
  • 16,397
  • 8
  • 68
  • 76
  • I also had to use `getChildFragmentManager()` instead of `getFragmentManager()` https://stackoverflow.com/a/19077209/2898715 – Eric Dec 05 '19 at 23:58
0

This is super late but I ran into this today and thought I'd write down my solution in case someone needs it.

The problem here is you are passing the VirsārstsFragment's ChildFragmentManager to SearchDialogFragment.

FragmentManager fm = getChildFragmentManager();
SearchDialogFragment dialog = new SearchDialogFragment();
dialog.show(fm, "searchDialog");

Instead you need to pass the normal fragment manager (get it by using getFragmentManager()).

I think your code doesn't because on a restore because the System looks for VirsārstsFragment in childFrgamentManager you passed to SearchDialogFragment but can not find it since VirsārstsFragment is actually in the activity's fragment manager. Passing the Activity's fragment manager to SearchDialogFragment fixes this.

-4

In case there is no UI change you can add the property configChanges to the activity in manifest

<activity
        android:name=".YourActivity"
        android:configChanges="screenSize|orientation"/>

What this does is it specifies that configuration changes when screensize or orientation changes are handled in the activity itself (in your case there is no change so no need to do anything)

In case you need to handle any changes in future you can do that in onConfigurationChanged() in your activity.

Let me know if this works in your case

pvn
  • 2,016
  • 19
  • 33