Callback to a Fragment from a DialogFragment
TargetFragment solution doesn't seem the best option for dialog fragments because it may create IllegalStateException
after application get destroyed and recreated. In this case FragmentManager
couldn't find the target fragment and you will get an IllegalStateException
with a message like this:
"Fragment no longer exists for key android:target_state: index 1"
It seems like Fragment#setTargetFragment()
is not meant for communication between a child and parent Fragment, but rather for communication between sibling-Fragments.
So alternative way is to create dialog fragments like this by using the ChildFragmentManager
of the parent fragment, rather then using the activities FragmentManager
:
dialogFragment.show(ParentFragment.this.getChildFragmentManager(), "dialog_fragment");
And by using an Interface, in onCreate
method of the DialogFragment
you can get the parent fragment:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
callback = (Callback) getParentFragment();
} catch (ClassCastException e) {
throw new ClassCastException("Calling fragment must implement Callback interface");
}
}
Only thing left is to call your callback method after these steps.
For more information about the issue, you can check out the link: https://code.google.com/p/android/issues/detail?id=54520
Activity involved is completely unaware of the DialogFragment.
Fragment class:
public class MyFragment extends Fragment {
int mStackLevel = 0;
public static final int DIALOG_FRAGMENT = 1;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
mStackLevel = savedInstanceState.getInt("level");
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("level", mStackLevel);
}
void showDialog(int type) {
mStackLevel++;
FragmentTransaction ft = getActivity().getFragmentManager().beginTransaction();
Fragment prev = getActivity().getFragmentManager().findFragmentByTag("dialog");
if (prev != null) {
ft.remove(prev);
}
ft.addToBackStack(null);
switch (type) {
case DIALOG_FRAGMENT:
DialogFragment dialogFrag = MyDialogFragment.newInstance(123);
dialogFrag.setTargetFragment(this, DIALOG_FRAGMENT);
dialogFrag.show(getFragmentManager().beginTransaction(), "dialog");
break;
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch(requestCode) {
case DIALOG_FRAGMENT:
if (resultCode == Activity.RESULT_OK) {
// After Ok code.
} else if (resultCode == Activity.RESULT_CANCELED){
// After Cancel code.
}
break;
}
}
}
}
DialogFragment class:
public class MyDialogFragment extends DialogFragment {
public static MyDialogFragment newInstance(int num){
MyDialogFragment dialogFragment = new MyDialogFragment();
Bundle bundle = new Bundle();
bundle.putInt("num", num);
dialogFragment.setArguments(bundle);
return dialogFragment;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new AlertDialog.Builder(getActivity())
.setTitle(R.string.ERROR)
.setIcon(android.R.drawable.ic_dialog_alert)
.setPositiveButton(R.string.ok_button,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_OK, getActivity().getIntent());
}
}
)
.setNegativeButton(R.string.cancel_button, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_CANCELED, getActivity().getIntent());
}
})
.create();
}
}
I followed this simple steps to do this stuff.
- Create interface like
DialogFragmentCallbackInterface
with some method likecallBackMethod(Object data)
. Which you would calling to pass data. - Now you can implement
DialogFragmentCallbackInterface
interface in your fragment likeMyFragment implements DialogFragmentCallbackInterface
At time of
DialogFragment
creation set your invoking fragmentMyFragment
as target fragment who createdDialogFragment
usemyDialogFragment.setTargetFragment(this, 0)
check setTargetFragment (Fragment fragment, int requestCode)MyDialogFragment dialogFrag = new MyDialogFragment(); dialogFrag.setTargetFragment(this, 1);
Get your target fragment object into your
DialogFragment
by callinggetTargetFragment()
and cast it toDialogFragmentCallbackInterface
.Now you can use this interface to send data to your fragment.DialogFragmentCallbackInterface callback = (DialogFragmentCallbackInterface) getTargetFragment(); callback.callBackMethod(Object data);
That's it all done! just make sure you have implemented this interface in your fragment.
Maybe a bit late, but may help other people with the same question like I did.
You can use setTargetFragment
on Dialog
before showing, and in dialog you can call getTargetFragment
to get the reference.