I have an AppCompatActivity
that, at some point, display a DialogFragment
. In this dialog, there are items for which I ask confirmation before deleting them. That confirmation is asked through another Yes/No DialogFragment
. When the user clicks Yes in that second dialog, I want the first dialog to refresh its ListView
(just need to update the adapter and call its notifyDataSetChanged
method). The problem is that I don't know when to update the listview.
Because that delete functionality is called from various sources, I implement a listener Interface at the activity level and call an "onDeleteRequest" event from that interface whenever I need an item to be deleted, and that's the activity who opens up the confirmation dialog and perform the actual delete.
Since I don't care much about refreshing the ListView in unnecessary situations, I tried to update the list in the onResume
event, but the event is not called when I come back to the first dialog after the confirmation one is dismissed.
So my question is: how can I know when a dialog B displayed on top of a dialog A has been dismissed so I can refresh dialog A accordingly?
EDIT : A bit of code to support my question:
My activity class:
public class MonthActivity
extends AppCompatActivity
implements OnEditCalendarsDialogListener
{
...
//That's where dialog A is shown
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
...
if (id == R.id.action_select_calendar) {
final CalendarSelection currentSelection = mCalendarSelectionAdapter.getCurrentCalendarSelection();
if (currentSelection != null) {
EditCalendarsDialogFragment dialogFragment = EditCalendarsDialogFragment.newInstance(currentSelection);
dialogFragment.show(getSupportFragmentManager());
}
return true;
}
return super.onOptionsItemSelected(item);
}
...
//OnEditCalendarsDialogListener interface implementation
//That's where Dialog B is shown over Dialog A
@Override
public void onEditCalendarsDialogDelete(long calendarID) {
final Repository repository = Repository.getInstance(this);
final Calendar calendar = repository.fetchOneByID(Calendar.class, calendarID);
if (calendar != null) {
YesNoDialog yesNoDialog = YesNoDialog.newInstance(this, R.string.yes_no_dialog_confirmation, R.string.yes_no_dialog_calendar_delete);
setCurrentOnDecisionClickListener(new OnPositiveClickListener() {
@Override
public boolean onPositiveClick(DialogInterface dialog) {
//Delete calendar
repository.delete(calendar);
//That's where I'd like to notify Dialog A that it needs to be refreshed
return true;
}
});
yesNoDialog.show(getSupportFragmentManager());
}
}
}
My dialog class
public class EditCalendarsDialogFragment
extends DialogFragment
{
private OnEditCalendarsDialogListener mDialogListener;
public static EditCalendarsDialogFragment newInstance(CalendarSelection calendarSelection) {
EditCalendarsDialogFragment dialog = new EditCalendarsDialogFragment();
Bundle arguments = new Bundle();
if (calendarSelection != null) {
arguments.putLong(KEY_ID, calendarSelection.getID());
}
else {
arguments.putLong(KEY_ID, 0L);
}
dialog.setArguments(arguments);
return dialog;
}
...
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mDialogListener = (OnEditCalendarsDialogListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnCalendarSelectionDialogListener");
}
}
...
private View getLayoutView() {
View rootView = getActivity().getLayoutInflater().inflate(R.layout.calendar_list, null, false);
if (rootView != null) {
mCalendars = (ListView) rootView.findViewById(R.id.calendars);
if (mCalendars != null) {
//Create adaptor
mCalendarAdapter = new ArrayAdapter<Calendar>(
getContext(),
android.R.layout.simple_list_item_2,
android.R.id.text1,
new ArrayList<Calendar>()
) {
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
View view = super.getView(position, convertView, parent);
final Calendar calendar = getItem(position);
if (calendar != null && calendar.hasID()) {
...
view.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (mDialogListener != null) {
//That's where I request delete from calling activity
mDialogListener.onEditCalendarsDialogDelete(calendar.getID());
}
return true;
}
});
}
return view;
}
};
mCalendars.setAdapter(mCalendarAdapter);
refreshCalendarList();
}
}
return rootView;
}
}
OK, so I finally used the "over-abusive-callback" method.
I created the following interface:
public interface OnDeletedListener {
void onDeleted();
}
Updated the OnEditCalendarsDialogListener interface so that the callback has a callback to this interface too:
public interface OnEditCalendarsDialogListener {
void onEditCalendarsDialogDelete(long calendarID, OnDeletedListener onDeletedListener);
}
Implemented the OnDeletedListener interface in "Dialog A" class:
public class EditCalendarsDialogFragment
extends DialogFragment
implements OnDeletedListener
{
...
//OnDeletedListener interface implementation
@Override
public void onDeleted() {
//That's where I'm called back after item is deleted
refreshCalendarList();
}
...
private View getLayoutView() {
...
view.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (mDialogListener != null) {
//That's where I request delete from calling activity, asking to call me back once deleted
mDialogListener.onEditCalendarsDialogDelete(calendar.getID(), EditCalendarsDialogFragment.this);
}
return true;
}
});
...
}
}
And finally, call the callback when delete is accepted and performed:
public class MonthActivity
extends AppCompatActivity
implements OnEditCalendarsDialogListener
{
//OnEditCalendarsDialogListener interface implementation
//That's where Dialog B is shown over Dialog A
@Override
public void onEditCalendarsDialogDelete(long calendarID, final OnDeletedListener onDeletedListener) {
final Repository repository = Repository.getInstance(this);
final Calendar calendar = repository.fetchOneByID(Calendar.class, calendarID);
if (calendar != null) {
YesNoDialog yesNoDialog = YesNoDialog.newInstance(this, R.string.yes_no_dialog_confirmation, R.string.yes_no_dialog_calendar_delete);
setCurrentOnDecisionClickListener(new OnPositiveClickListener() {
@Override
public boolean onPositiveClick(DialogInterface dialog) {
//Delete calendar
repository.delete(calendar);
//That's where I notify Dialog A that it needs to be refreshed
if (onDeletedListener != null) {
onDeletedListener.onDeleted();
}
return true;
}
});
yesNoDialog.show(getSupportFragmentManager());
}
}
}
Works smoothly!