9

少し障害物にぶつかりました。DialogFragment - 画面の回転後にリスナーを保持するで説明されているものと非常によく似たシナリオがあります

作成者のダイアログはアクティビティから呼び出されているため、提案されたソリューションは作成者にとってうまく機能します。私の場合もまったく同じですが、カスタム ダイアログはアクティビティではなくフラグメントから呼び出されます。(IE アクティビティ -> フラグメント -> ダイアログ)

私は同じ解決策を実装しました (呼び出し元の Fragment から onResume でリスナーを設定します) が、この場合は機能しません。

何が起こっているように見えるかは、画面が回転すると、Android がダイアログとフラグメントを強制終了することです。次に、その順序でそれらを再作成します。そのため、カスタム ダイアログで onCreateDialog が呼び出されたとき、含まれている Fragment はまだ再作成されていないため、リスナーが正と負のボタンに設定する 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;
    }
}
4

2 に答える 2

4

議論されたリンクのすべてのオプションを実行しましたが、解決策はどれもうまくいきませんでした. get/setTargetFragment や FragmentManager.put/getFragment など、さらにグーグルで検索した後、いくつかの追加オプションも試しました。これらも私にはうまくいきませんでした。次に、次のことをもう一度調べました。

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

彼らが具体的に「2つのフラグメントは直接通信してはならない」と言っているところ。これは、それが本当に真実であることが証明されたケースの1つだと思います。

そこで提供されている提案されたコールバックメカニズムを実装することになり、最終的には次のようになりました。

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);
}

FragmentDialog を起動する Fragment では、次のようになります。

public static final String TAG = "tag1";

public void applyStepEdit(int pos, String description) {
    ...
}

これは完全に機能し、開いてから方向の変更と編集が完了すると、クラッシュしたり何もしない (null リスナー) 代わりに、呼び出し元の Fragment で実行する必要がある最終的な関数が実際にトリガーされます。

于 2013-09-26T23:54:33.310 に答える