ほりすのぶろぶろぶろぐ

ほりすのぶろぶろぶろぐ

非情報系から最高のエンジニアを目指す旧帝大学生

【Android】FragmentでDialogFragmentを使う

自作アプリを作る際、Fragmentで購入ボタンを押したらダイアログを表示させたかったのですがうまくいかず、2~3時間ほど悩んでいたので、解決までに歩んだ道のりを備忘録として記したいと思います。

困っていたこと

購入ボタンを押したらダイアログは表示されるのですが、OKボタンを押すとdialogFragmentListener.onDialogPositiveButtonClicked()の行でClassCastExceptionが投げられる。

以下が変更前のコード。

public class MyDialogFragment extends DialogFragment {

    private DialogFragmentListener dialogFragmentListener;

    public interface DialogFragmentListener{
       void onDialogPositiveButtonClicked();
    }

    public MyDialogFragment newInstance(DialogFragmentListener dialogFragmentListener){
         this.dialogFragmentListener = dialogFragmentListener;
   return new MyDialogFragment();
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {

        AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(getActivity())
                .setTitle("購入")
                .setMessage("購入しますか?")
                .setPositiveButton("購入する", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialogFragmentListener.onDialogPositiveButtonClicked();
                    }
                })
                .setNegativeButton("やめる", null);

        return dialogBuilder.create();
    }

解決までの道のり

えっ、クラスキャストできてないの?とひたすらDialogFragmentについて調べていたら、どうやらActivityから使用するDialogFragmentと、Fragmentから使用するのとでは違うみたいでした。

 @Override
    public void onAttach(Context context) {
        super.onAttach(context);

        Fragment targetFragment = this.getTargetFragment();
        try{
            if(targetFragment != null){
                dialogFragmentListener = (DialogFragmentListener)targetFragment;
            }
        }catch (ClassCastException e){
            throw new ClassCastException("DialogFragmentListenerをimplementしていません");
        }
    }

上記のコードを追加し、Fragmentからも呼び出せるようにした、、つもりだったが、今度は同じ行でNullPointerExceptionが投げられた。
どこでぬるぽが起きているのかをDebugモードで見てみたところ、onAttach内のtargetFragmentがnullということが分かりました。

    public MyDialogFragment newInstance(Fragment fragment){
   MyDialogFragment instance = new MyDialogFragment();
        instance.setTargetFragment(fragment, 0);
        return instance;
    }

を追加して解決しました。
TargetFragmentに呼び出し元のFragmentを渡してあげないといけなかったみたいですね。
ようやく解決したのでとりあえずはよかった...。