I'm switching one of my applications over to fragments (from just activities) and either I'm totally missing something or they have severely complicated the whole process of showing an AlertDialog.
First, here's what I'm trying to do: show one of several alert dialogs with a positive and negative button with callback methods associated to each bottom. Dialog needs to survive (ie: be recreated) a screen rotation.
Before: In the past, all you had to do is create an AlertDialog with the proper callback methods, etc. and show it and the system would take care of everything including screen rotation.
Now: If I create and show an AlertDialog from my fragment, it doesn't get recreated during a screen rotation and according to the LogCat leaks memory during the destruction. According to the new developer docs on fragments, I should be using a DialogFragment to create a AlertDialog so that the fragment manager can handle things like screen rotation, etc. (see here: http://developer.android.com/reference/android/app/DialogFragment.html under the Alert Dialog heading) That's fine, however, the problem is the callback methods. In the provided example, they are hard coded to two methods in the Activity. I have two problems with that, I don't want to have the activity involved in this process, and I need different callback methods for different AlertDialog I create. I really don't want to have to create different classes with hard coded callbacks for each AlertDialog I will be creating. There has to be a simpler way, otherwise this is just stupidity :)
Another way to put things ... fragments are recreated after a screen rotation by the fragment manager using any "arguments" that were saved during the creation process. These arguments are saved inside a Bundle, however, I can't save a callback method inside a Bundle, hence the fragment manager can't recreate a fragment with a passed callback method, only a hard coded one, which means I need separate classes with hard coded callback methods for each type of AlertDialog I will be displaying ... is this stupid or am I just missing something here?
Thanks for any help, Harry
You can use interfaces to tidy up the hardcoded callbacks a bit.
In the following sample, my dialog fragment class specifies an interface called Host. Activities that want to use this fragment will have to implement MyAlertDialog.Host interface and have the two methods it defines. Of course, instead of generic onOptionOne and onOptionTwo names you could use onReport, onRetry --whatever makes sense for each alert.
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
public class MyAlertDialog extends DialogFragment {
/**
* Host activities have to implement this interface to receive button click
* callbacks.
*
*/
public static interface Host {
public void onOptionOne();
public void onOptionTwo();
}
public static MyAlertDialog newInstance() {
return new MyAlertDialog();
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
DialogInterface.OnClickListener clickListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Host host;
try {
host = (Host) getActivity();
} catch (ClassCastException e) {
String name = getActivity().getClass().getName();
throw new RuntimeException("Class " + name + " doesn't implement MyAlertDialog.Host interface");
}
if (which == DialogInterface.BUTTON_POSITIVE)
host.onOptionOne();
if (which == DialogInterface.BUTTON_NEGATIVE)
host.onOptionTwo();
}
};
return new AlertDialog.Builder(getActivity())
.setMessage("Message here")
.setPositiveButton("Option One", clickListener)
.setNegativeButton("Option Two", clickListener)
.create();
}
}
The upside of this is, MyAlertDialog doesn't reference any specific activities. When an activity chooses to use this dialog, it has to implement its contract. That, instead of other way around, where dialog would be coupled with activities and would hook into them.
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