如何在片段打开的自定义对话框中保留监听器?

use*_*491 9 android android-lifecycle android-fragments android-dialogfragment

我遇到了一些障碍.我有一个非常类似于下面描述的场景:DialogFragment - 在屏幕旋转后保留监听器

建议的解决方案适用于作者,因为他的对话框是从活动中调用的.我的情况完全相同,但我的自定义对话框是从片段而不是活动调用的.(IE Activity-> Fragment-> Dialog)

我实现了相同的解决方案(在调用Fragment中设置onResume中的监听器)但在这种情况下它不起作用.

似乎正在发生的事情是,当屏幕旋转时,Android会杀死Dialog和Fragment.然后按顺序重新创建它们.因此,当我的自定义对话框上调用onCreateDialog时,包含的片段尚未重新创建,因此它为侦听器设置为正和负按钮时为null.

有没有人知道这方面的方法?

如果有人认为有必要,我可以发布代码,但它与链接线程上的代码几乎相同.

更新代码:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

use*_*491 4

我浏览了所讨论的链接上的所有选项,但没有一个解决方案最终对我有用。在进一步谷歌搜索后,我还尝试了一些其他选项,例如 get/setTargetFragment 和 FragmentManager.put/getFragment。这些对我来说也不起作用。然后我又看了一眼:

http://developer.android.com/training/basics/fragments/communicating.html

他们特别说“两个片段不应该直接通信”。我认为这是真正证明这一点的案例之一。

我最终实现了那里提供的建议回调机制,并最终得到以下结果:

在对话框片段中:

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");
    }
}
Run Code Online (Sandbox Code Playgroud)

在主持活动中:

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);
}
Run Code Online (Sandbox Code Playgroud)

在触发 FragmentDialog 的 Fragment 中:

public static final String TAG = "tag1";

public void applyStepEdit(int pos, String description) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

这工作得很好,如果打开然后方向更改并完成编辑,它实际上会触发我需要在调用片段中运行的最终功能,而不是崩溃或不执行任何操作(空侦听器)。