I have fragment that on a component click pop-ups DialogFragment. This dialog fragment holds list of options. When an option from list is selected I want to notify fragment so I can run fields update procedure. I did something like this
@Override
public void onClick(DialogInterface dialog, int item) {
updateSharedPreference(item);
Log.e("ProfilePersonaListDialog", "Click on dialog, inside onClick");
OnCloseListDialogListener act = (OnCloseListDialogListener) getActivity();
act.onDialogListSelection();
dismiss();
}
However this getActivity() calls on FragmentActivity and not the fragment that triggered the dialog fragment. I could kill currently open/running fragment and call a new instance that would get updated fields, but that is dirty solution that I would prefer to avoid.
Any suggestions how to go about this update of fragment once option selected in dialog fragment?.
Just coming back with solution. My problem was actually forwarding current fragment getTag() string as parameter of show() for DialogFragment. If anyone interested here is working sample.
Create simple listener
public interface OnCloseListDialogListener {
public void onDialogListSelection();
}
Create new dialog that will extend DialogFragment
public class ListDialogFragment extends DialogFragment implements DialogInterface.OnClickListener {
private PersonaData[] mPersonaData;
private String[] mPersonaName;
private final String TAG;
public static ListDialogFragment newInstance(PersonaData[] personaData, String tag) {
ListDialogFragment dialog = new ListDialogFragment(personaData, tag);
Bundle bundle = new Bundle();
dialog.setArguments(bundle);
return dialog;
}
private ListDialogFragment(PersonaData[] personaData, String tag) {
this.mPersonaData = personaData.clone();
this.TAG = tag;
}
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setCancelable(true);
int style = DialogFragment.STYLE_NORMAL, theme = 0;
setStyle(style, theme);
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.dialog_title);
mPersonaName = getData();//Your own implementation here
builder.setNegativeButton("Cancel", this);
builder.setSingleChoiceItems(mPersonaName, -1, new SingleChoiceListener());
return builder.create();
}
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
private class SingleChoiceListener implements DialogInterface.OnClickListener {
@Override
public void onClick(DialogInterface dialog, int item) {
updateSharedPreference(item);
OnCloseListDialogListener act = (OnCloseListDialogListener) getFragmentManager().findFragmentByTag(TAG);
act.onDialogListSelection();
dismiss();
}
}
}
And then in fragment from which you wish to call this dialog do as bellow. DIALOG is just String constant I put there just dialog
SOME_CLICKABLE.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
FragmentManager manager = getFragmentManager();
ListDialogFragment dialog = ListDialogFragment.newInstance(mPersona, getTag());
dialog.show(manager, DIALOG);
}
});
It is necessary in most cases that a Fragment
be aware that it is running under the context of an Activity
of some description and acceptable for the child Fragment to invoke a method on an interface implicitly implemented by the parent Activity (as demonstrated by the cast in your code snippet). When you get your references working as Tomasz points out you'll be golden.
However, :) to aid the re-usability of the dialog fragment I would suggest that you leverage BroadcastReceiver
s. A BroadcastReceiver simply broadcasts a message saying I did 'x'. The parent activity or in indeed any other top level component can then declare I am listening for 'x'. Once, the event has been fired in the dialog component, this event will be collected by the parent Activity's onReceive
where you can run the necessary code to update your fields.
On a personal level, I prefer this loose coupling over the casting interface approach since it forces me to think about the purpose of each Fragment and keep it modular.
If you want to give it a shot then have a read over the dev guide section on BroadcastReceivers and follow the follow steps;
Implement the BroadcastReceiver
in your parent activity. Notice an onReceive
method is required to be implemented.
Override the parent Activity's onResume
method and register the the activity as a receiver of an event with intent action "blah". Something like;
@Override
protected void onResume() {
super.onResume();
registerReceiver(this, new IntentFilter("blah"));
}
Override the parent Activity's onPause
method an unregister the activity as the receiver so as to avoid 'leaked receivers' (you'll find out).
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(deleteSpotReceiver);
}
In your DialogFragment
onClick
fire the event which your parent activity is 'listening' for.
@Override
public void onClick(DialogInterface dialog, int item) {
updateSharedPreference(item);
Log.e("ProfilePersonaListDialog", "Click on dialog, inside onClick");
final Intent intent = new Intent();
intent.setAction("blah");
getActivity().sendBroadcast(intent);
dismiss();
}
The parent activity will collect the message and you can continue processing. Let me know if you decide to adopt that method.
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