web-dev-qa-db-ja.com

DialogFragment-画面の回転後にリスナーを保持する

DatePickerDialogを作成するDialogFragmentがあります。デフォルトの空のコンストラクターを使用するために、newInstanceという静的メソッドを使用して初期値を設定しています。ただし、リスナーをどのように設定する必要がありますか?画面回転後、「完了」ボタンをクリックすると、リスナーは存在しないため何もしません。

public class DatePickerFragment extends DialogFragment {
    public static final String ARG_YEAR = "year";
    public static final String ARG_MONTH = "month";
    public static final String ARG_DAY = "day";

    private OnDateSetListener listener_;

    public static DatePickerFragment newInstance(OnDateSetListener listener, int year, int month, int day) {
        final DatePickerFragment date_picker = new DatePickerFragment();
        date_picker.setListener(listener);

        final Bundle arguments = new Bundle();
        arguments.putInt(ARG_YEAR, year);
        arguments.putInt(ARG_MONTH, month);
        arguments.putInt(ARG_DAY, day);
        date_picker.setArguments(arguments);

        return date_picker;
    }

    private void setListener(OnDateSetListener listener) {
        listener_ = listener;
    }

    @Override
    public Dialog onCreateDialog(Bundle saved_instance_state) {
        final Bundle arguments = getArguments();
        final int year = arguments.getInt(ARG_YEAR);
        final int month = arguments.getInt(ARG_MONTH);
        final int day = arguments.getInt(ARG_DAY);

        return new DatePickerDialog(getActivity(), listener_, year, month, day);
    }
}
30

ただし、リスナーをどのように設定する必要がありますか?

リスナー参照は、onCreateActivityメソッドで更新します。

private OnDateSetListener mOds = new OnDateSetListener() {

    @Override
    public void onDateSet(DatePicker view, int year, int monthOfYear,
            int dayOfMonth) {
             // do important stuff
    }
};

およびonCreateメソッドの場合:

if (savedInstanceState != null) {
    DatePickerFragment dpf = (DatePickerFragment) getSupportFragmentManager()
            .findFragmentByTag("theTag?");
    if (dpf != null) {
        dpf.setListener(mOds);
    }
}
62
Luksprog

私の意見では、フラグメントのライフサイクルを使用して、これを行うためのより効率的な方法があります。 FragmentライフサイクルコールバックonAttach()およびonDetach()を使用して、次のようにアクティビティをリスナーとして自動的にキャストできます。

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    try {
        _listener = (OnDateSetListener)activity;
    } catch(ClassCastException e) {
        // check if _listener is null before using,
        // or throw new ClassCastException("hosting activity must implement OnDateSetListener");
    }
}

@Override
public void onDetach() {
    super.onDetach();
    _listener = null;
}

このテクニックは公式に文書化されています ここ

7
d370urn3ur

Luksprogの答えは正しいです。指摘したいのですが、ソリューションの鍵はfindFragmentByTag()関数です。画面の回転後にアクティビティも再作成されるため、そのメンバーであるFragment変数のsetter関数を呼び出すことはできません。代わりに、この関数を使用して古いフラグメントインスタンスを見つける必要があります。

ところで、DialogFragment.show()を呼び出すとき、タグは2番目のパラメーターです。

2
cn123h