我正在将我的一个应用程序切换到片段(仅来自活动),或者我完全错过了某些内容,或者他们在显示AlertDialog的整个过程中都非常复杂。
首先,这是我正在尝试做的事情:显示一个带有正负按钮的警告对话框,其中每个底部都有一个回调方法。对话需要生存(即:重新创建)一个屏幕旋转。
之前:在过去,您所要做的就是使用正确的回调方法等创建一个AlertDialog并显示它,系统会处理所有事情,包括屏幕旋转。
现在:如果我从片段创建并显示AlertDialog,则在屏幕旋转期间不会重新创建它,并且根据LogCat在销毁期间泄漏内存。根据关于片段的新开发人员文档,我应该使用DialogFragment来创建一个AlertDialog,以便片段管理器可以处理屏幕旋转等内容(请参阅此处:警告对话框标题下的http://developer.android.com/reference/android/app/DialogFragment.html)那很好但是,问题是回调方法。在提供的示例中,它们被硬编码为Activity中的两个方法。我有两个问题,我不想让这个过程涉及活动,我需要为我创建的不同AlertDialog提供不同的回调方法。我真的不想为我将要创建的每个AlertDialog创建带有硬编码回调的不同类。必须有一个更简单的方法,否则这只是愚蠢:)
片段管理器使用在创建过程中保存的任何“参数”在屏幕旋转后重新创建另一种放置...片段的方法。这些参数保存在Bundle中,但是,我无法在Bundle中保存回调方法,因此片段管理器无法使用传递的回调方法重新创建片段,只能使用硬编码方法,这意味着我需要单独的类使用每种类型的AlertDialog的硬编码回调方法,我将显示...这是愚蠢的还是我只是在这里遗漏了什么?
感谢您的帮助, 哈利
答案 0 :(得分:1)
您可以使用接口来整理硬编码的回调。
在下面的示例中,我的对话框片段类指定了一个名为Host
的接口。想要使用此片段的活动必须实现MyAlertDialog.Host
接口并具有它定义的两种方法。当然,您可以使用onOptionOne
,onOptionTwo
代替通用onReport
和onRetry
名称 - 对每个警报都有意义。
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();
}
}
这方面的好处是,MyAlertDialog
没有提到任何具体的活动。当一个活动选择使用该对话框时,它必须实现其合同。而不是以其他方式,对话将与活动相结合,并将它们挂钩。
答案 1 :(得分:0)
调用setRetainInstance(true)将导致FragmentManager保存实际的Fragment实例。它不会破坏和重新创建片段,而是将相同的片段传递给新的Activity。
使用setRetainInstance(true)要注意的主要事情是,一个Fragment实例可能会在Fragment的生命周期中看到对onCreateView()和onDestroyView()的多次调用,因为它与不同的Activity相关联。如果是,例如你在onCreateView()中注册了一个BroadcastReceiver并在onDestroy()中注册了它,你的代码可以正常使用setRetainInstance(false),但不能使用setRetainInstance(true)。
编辑 - 这个答案不仅错误,而且我am in the discussion for the related issue!
所以我应该得到所有的支持。 :) setRetainInstance(true)上有一个错误,你可以用一个严重的黑客修复 - 在你的DialogFragment的onDestroyView()中调用getDialog()。setDismissMessage(null)来破解它。