我遇到了一些障碍。我的场景非常类似于DialogFragment - retaining listener after screen rotation
中描述的场景建议的解决方案适用于作者,因为他的对话框是从活动中调用的。我的情况完全相同,但我的自定义对话框是从片段而不是活动调用的。 (IE Activity-> Fragment-> Dialog)
我实现了相同的解决方案(在调用Fragment中设置onResume中的侦听器)但在这种情况下它不起作用。
似乎正在发生的事情是,当屏幕旋转时,Android会杀死对话框和片段。然后按顺序重新创建它们。因此,当我的自定义对话框中调用onCreateDialog时,仍然需要重新创建包含片段的片段,因此它为侦听器设置为正和负按钮时为空。
有没有人知道解决这个问题?
如果有人认为有必要,我可以发布代码,但它与链接线程上的代码几乎相同。
更新代码:
public class RecipeDetailEditFragment extends SherlockFragment implements DialogInterface.OnClickListener {
private EditStepFragmentDialog stepDialog;
private Recipe newRecipe; //main data object implements parcelable
...
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
stepDialog = EditStepFragmentDialog.newInstance(newRecipe);
//I've also tried passing 'this' into the newInstance constructor and
//setting the listener there, but that doesn't work either
}
public void onResume() {
stepDialog.setListener(this);
super.onResume();
}
...
}
public class EditStepFragmentDialog extends DialogFragment {
private DialogInterface.OnClickListener ocl;
private static final String ARG_RECIPE = "recipe";
private Recipe recipe;
public EditStepFragmentDialog() {}
public static EditStepFragmentDialog newInstance(Recipe rec) { //(Recipe rec, DialogInterface.OnClickListener oc) as mentioned doesn't work.
EditStepFragmentDialog dia = new EditStepFragmentDialog();
Bundle args = new Bundle();
args.putParcelable(ARG_RECIPE, rec);
//dia.setListener(oc);
return dia;
}
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder adb = new AlertDialog.Builder(getActivity());
if (getArguments().containsKey(ARG_RECIPE)) {
recipe = (Recipe) getArguments().getParcelable(ARG_RECIPE);
}
...
adb.setPositiveButton("Done", ocl);
adb.setNegativeButton("Cancel", ocl);
...
return adb.create();
}
public void setListener(DialogInterface.OnClickListener cl) {
ocl = cl;
}
}
答案 0 :(得分:4)
我查看了所讨论链接的所有选项,但没有一个解决方案最终为我工作。在进一步使用go / setTargetFragment和FragmentManager.put / getFragment之后,我还尝试了许多其他选项。这些对我来说也不起作用。然后我再看看:
http://developer.android.com/training/basics/fragments/communicating.html
他们具体说“两片碎片不应该直接沟通”。我认为这是真正证明是真实的案例之一。
我最终实现了那里提供的建议回调机制,并最终得到了这个:
在DialogFragment中:
public interface OnEditStepDialogListener {
public void onEditStepDialogPositive(int pos, String description);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mCallback = (OnEditStepDialogListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnEditStepDialogListener");
}
}
在托管活动中:
public class MyActivity extends SherlockFragmentActivity implements EditStepFragmentDialog.OnEditStepDialogListener {
...
@Override
public void onEditStepDialogPositive(int pos, String desc) {
FragmentManager fm = getSupportFragmentManager();
RecipeDetailEditFragment ef = (RecipeDetailEditFragment)fm.findFragmentByTag(RecipeDetailEditFragment.TAG);
ef.applyStepEdit(pos, desc);
}
在Fragment中激活FragmentDialog:
public static final String TAG = "tag1";
public void applyStepEdit(int pos, String description) {
...
}
这很好用,如果打开然后方向更改和编辑完成,它实际上会触发我需要在调用Fragment中运行的最终函数,而不是崩溃或不执行任何操作(null侦听器)。
答案 1 :(得分:0)
报告回您的活动并创建对话框会是一场灾难吗?
我刚刚查看了我的代码,看看我在做什么,因为我没有遇到过这个问题。我对它的看法是这样的:
- MyActivity
|
---- MapsFragmet (for example)
|
---- DirectionsModule (simple class that is handed Context)
|
---- PointsOfInterestModule (simple class that is handed Context)
因此,使用此构造,活动仅使用片段来显示地图,但可以将其用于指示目的或兴趣点,具体取决于调用哪个模块。
现在,当模块遇到问题或需要用户交互时,它会向MyActivity报告,然后再显示一个DialogFragment。
想要给出一个更好的答案,因为我不明白为什么你不能从另一个片段中调用DialogFragment并期望一个好的行为。
以防万一,你有没有在Fragment上设置setRetainInstance(true)?
修改强>
好的,我刚刚审核了你新提交的代码,这是我的新想法:
扩展对话框的参数以获取上下文,以便您可以这样调用它:
stepDialog = EditStepFragmentDialog.newInstance(getActivity(), newRecipe);
接下来在对话框中使用添加的上下文而不是getActivity():
AlertDialog.Builder adb = new AlertDialog.Builder(context);
我怀疑(不确定)SherlockFragment被视为Activity的一个实例,因此当您在对话框中调用getActivity()时,它会与您的片段绑定。