前提
ダイアログの上にダイアログを表示し、リスナーを使用して値をフラグメントに送りたいです。
今までViewModelを使って行っていましたが、リスナーを使う方法に変えたいです。
実現したいこと
①フラグメント表示
②フラグメント上のボタンクリックでダイアログ_0表示(1つ目のダイアログ)
③ダイアログ0上のボタンクリックでダイアログ_1表示(2つ目のダイアログ)
④ダイアログ1上のボタンクリックで値をフラグメントに送る
③までできています。④を行うと、エラーになり、画面が消えます。
エラーメッセージ
java.lang.NullPointerException: Attempt to invoke interface method 'void tmaruko.okura.test1.SampleDialogFragment$SampleDialogListener.send_receive2(androidx.fragment.app.DialogFragment)' on a null object reference
MainActivity.java
java
1public class MainActivity extends AppCompatActivity { 2 3 @Override 4 protected void onCreate(Bundle savedInstanceState) { 5 super.onCreate(savedInstanceState); 6 setContentView(R.layout.activity_main); 7 8 // Activityにフラグメントをセット 9 getSupportFragmentManager() 10 .beginTransaction() 11 .add(R.id.fragment_sample, new SampleFragment()) 12 .commit(); 13 } 14}
SampleFragment.java
java
1// インターフェースを実装するためにimplementsする 2public class SampleFragment extends Fragment implements SampleDialogFragment.SampleDialogListener { 3 4 private Button button; 5 6 @Override 7 public View onCreateView(LayoutInflater inflater, ViewGroup container, 8 Bundle savedInstanceState) { 9 View view = inflater.inflate(R.layout.fragment_sample, container, false); 10 11 // アクションバーにタイトルをセット 12 MainActivity activity = (MainActivity) getActivity(); 13 activity.setTitle("ダイアログコールバックサンプル"); 14 15 // ボタン要素をレイアウトから取得 16 button = view.findViewById(R.id.bt_show_dialog); 17 button.setText("ダイアログ表示する"); 18 19 // ボタンクリックされたときの処理 20 button.setOnClickListener(new View.OnClickListener() { 21 @Override 22 public void onClick(View view) { 23 // フラグメントマネージャーを取得 24 FragmentManager fragmentManager = getActivity().getSupportFragmentManager(); 25 // SampleDialogFragmentのインスタンスオブジェクトを生成 26 SampleDialogFragment dialogFragment = SampleDialogFragment.newInstance(); 27 // SampleDialogFragmentのオブジェクトに呼び出し元のSampleFragmentオブジェクトをセット 28 dialogFragment.setTargetFragment(SampleFragment.this, 0); 29 // ダイアログを表示 30 dialogFragment.show(fragmentManager, ""); 31 } 32 }); 33 return view; 34 } 35 36 // コールバックされて実行される処理 37 @Override 38 public void send_receive(DialogFragment dialog) { 39 // ボタンに表示されている文字を変更 40 button.setText("dialog_0からきたよ"); 41 } 42 43 @Override 44 public void send_receive2(DialogFragment dialog) { 45 button.setText("dialog_1からきたよ"); 46 } 47} 48
SampleDialogFragment.java
java
1public class SampleDialogFragment extends DialogFragment { 2 static int no; 3 4 // インスタンスを生成するメソッド 5 public static SampleDialogFragment newInstance() { 6 return new SampleDialogFragment(); 7 } 8 9 // イベントのコールバックを受け取るためのインターフェースを実装 10 public interface SampleDialogListener { 11 void send_receive(DialogFragment dialog); 12 void send_receive2(DialogFragment dialog); 13 } 14 15 // クリックイベント発火を伝えるために使用するインターフェースインスタンスを定義 16 private SampleDialogListener listener; 17 18 // onAttach()で呼び出し元の親フラグメントがインターフェースを実装しているかを検証 19 // onAttach(): フラグメントのライフサイクルで最初に呼ばれるメソッドであり、 20 // フラグメントがアクティビティと関連づけられたときに一度だけ呼び出される。contextには所属親アクティビティが入っている・・・② 21 @Override 22 public void onAttach(Context context) { 23 super.onAttach(context); 24 try { 25 // 親フラグメントにイベントを送信できるように呼び出し元であるSampleFragmentオブジェクトを取得し、 26 // listenerのインスタンスを生成する 27 listener = (SampleDialogListener) getTargetFragment(); 28 } catch (ClassCastException e) { 29 // 親フラグメントがインターフェースを実装していない場合は例外を投げる 30 throw new ClassCastException(getTargetFragment().toString() + "はインターフェースを実装していません"); 31 } 32 } 33 @Override 34 public Dialog onCreateDialog(Bundle savedInstanceState) { 35 AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 36 switch (no) { 37 case 0: 38 //XMLとの紐付け 39 LayoutInflater inflater = getActivity().getLayoutInflater(); 40 View view = inflater.inflate(R.layout.dialogfragment_sample, null, false); 41 //ダイアログの作成 42 builder.setView(view); 43 //ボタンのリスナー 44 Button setumei_bt_tojiru = view.findViewById(R.id.setumei_bt_tojiru); 45 setumei_bt_tojiru.setOnClickListener(new View.OnClickListener() { 46 @Override 47 public void onClick(View view) { 48 // 処理を親のフラグメントにコールバックする 49 listener.send_receive(SampleDialogFragment.this); 50 dismiss(); 51 } 52 }); 53 Button setumei_bt_aitemu = view.findViewById(R.id.setumei_bt_aitemu); 54 setumei_bt_aitemu.setOnClickListener(new View.OnClickListener() { 55 @Override 56 public void onClick(View v) { 57 DialogFragment dialog = new SampleDialogFragment(); 58 no = 1;//アイテムダイアログに進む 59 dialog.show(getParentFragmentManager(), ""); 60 } 61 }); 62 break; 63 case 1:inflater=LayoutInflater.from(getActivity());//アイテム使用するかダイアログ 64 view=inflater.inflate(R.layout.dialogfragment_sample2,null); 65 //ダイアログの作成 66 builder.setView(view); 67 builder.setPositiveButton("つかう", new DialogInterface.OnClickListener() { 68 @Override 69 public void onClick(DialogInterface dialogInterface, int i) { 70 // 処理を親のフラグメントにコールバックする 71 listener.send_receive2(SampleDialogFragment.this);★ここがエラーになる 72 dismiss(); 73 } 74 }); 75 break; 76 } 77 AlertDialog dialog = builder.create(); 78 dialog.setCanceledOnTouchOutside(false); 79 //ダイアログ以外の画面をタップしてもダイアログは消えない 80 return dialog; 81 } 82}
試したこと
②(1つ目のダイアログ)でコールバックを行うとできます。
ということは、ダイアログを2つ重ねることで、フラグメントとのつながりが切れてしまうのではないかと思います。
教えていただきたいです。よろしくお願いします。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2022/12/27 23:37
2022/12/28 07:01 編集
2023/01/02 10:43
2023/01/02 11:02