回答編集履歴

5

コード修正

2024/10/30 13:38

投稿

jimbe
jimbe

スコア13170

test CHANGED
@@ -20,6 +20,8 @@
20
20
  B() { Fragment createFragment() { return new BFragment(); } };
21
21
  abstract Fragment createFragment();
22
22
  }
23
+
24
+ private static String TELEGRAM_ALERT_DIALOG_TAG = "TelegramAlertDialog";
23
25
 
24
26
  @Override
25
27
  protected void onCreate(Bundle savedInstanceState) {
@@ -37,8 +39,9 @@
37
39
  });
38
40
 
39
41
  model.getTelegramErrorCode().observe(this, errorCode -> {
40
- if(errorCode == null || errorCode.isEmpty()) return;
42
+ if(errorCode == null || errorCode.isEmpty() || fm.findFragmentByTag(TELEGRAM_ALERT_DIALOG_TAG) != null) return;
41
- AlertDialogFragment.getInstance(errorCode).show(fm, null);
43
+ AlertDialogFragment.getInstance(errorCode).show(fm, TELEGRAM_ALERT_DIALOG_TAG);
44
+ model.setTelegramErrorCode(null);
42
45
  });
43
46
 
44
47
  if(savedInstanceState == null) {
@@ -71,6 +74,9 @@
71
74
  private MutableLiveData<String> telegramErrorCodeLiveData = new MutableLiveData<>();
72
75
  LiveData<String> getTelegramErrorCode() {
73
76
  return telegramErrorCodeLiveData;
77
+ }
78
+ void setTelegramErrorCode(String errorCode) {
79
+ telegramErrorCodeLiveData.setValue(errorCode);
74
80
  }
75
81
 
76
82
  void startThread() {

4

誤字

2024/10/25 15:38

投稿

jimbe
jimbe

スコア13170

test CHANGED
@@ -47,7 +47,7 @@
47
47
  }
48
48
  }
49
49
  ```
50
- layout/acticity_main.xml
50
+ layout/activity_main.xml
51
51
  ```xml
52
52
  <?xml version="1.0" encoding="utf-8"?>
53
53
  <androidx.fragment.app.FragmentContainerView xmlns:android="http://schemas.android.com/apk/res/android"

3

サンプルコード追加

2024/10/25 15:36

投稿

jimbe
jimbe

スコア13170

test CHANGED
@@ -2,3 +2,263 @@
2
2
  (質問ではBからAへの遷移が常に成功する前提のようですが、遷移した瞬間にAが居なくなる可能性もあります。)
3
3
  アクティビティをアプリで1つだけとし、各画面をフラグメントで構成してフラグメントを入れ換えることで画面遷移を実現すれば、悩まずに済むと思います。
4
4
  (ついでに、ダイアログもそのまま使うとアクティビティが再生成されたときにダイアログは再生成されません。ダイアログフラグメントを使うと再生成されます。)
5
+
6
+ ---
7
+ テキトウに作ったサンプルです。AからBに行きスレッドを実行すると3秒後(その間にAに戻って)ダイアログが出ます。
8
+
9
+ MainActivity.java
10
+ ```java
11
+ import androidx.appcompat.app.AppCompatActivity;
12
+ import androidx.fragment.app.*;
13
+ import androidx.lifecycle.*;
14
+
15
+ import android.os.Bundle;
16
+
17
+ public class MainActivity extends AppCompatActivity {
18
+ enum Transfer {
19
+ A() { Fragment createFragment() { return new AFragment(); } },
20
+ B() { Fragment createFragment() { return new BFragment(); } };
21
+ abstract Fragment createFragment();
22
+ }
23
+
24
+ @Override
25
+ protected void onCreate(Bundle savedInstanceState) {
26
+ super.onCreate(savedInstanceState);
27
+ setContentView(R.layout.activity_main);
28
+
29
+ FragmentManager fm = getSupportFragmentManager();
30
+
31
+ MainViewModel model = new ViewModelProvider(this).get(MainViewModel.class);
32
+ model.getTransfer().observe(this, transfer -> {
33
+ if(transfer == null) return;
34
+ fm.beginTransaction()
35
+ .replace(R.id.fragment_container_view, transfer.createFragment())
36
+ .commit();
37
+ });
38
+
39
+ model.getTelegramErrorCode().observe(this, errorCode -> {
40
+ if(errorCode == null || errorCode.isEmpty()) return;
41
+ AlertDialogFragment.getInstance(errorCode).show(fm, null);
42
+ });
43
+
44
+ if(savedInstanceState == null) {
45
+ model.setTransfer(Transfer.A);
46
+ }
47
+ }
48
+ }
49
+ ```
50
+ layout/acticity_main.xml
51
+ ```xml
52
+ <?xml version="1.0" encoding="utf-8"?>
53
+ <androidx.fragment.app.FragmentContainerView xmlns:android="http://schemas.android.com/apk/res/android"
54
+ android:id="@+id/fragment_container_view"
55
+ android:layout_width="match_parent"
56
+ android:layout_height="match_parent" />
57
+ ```
58
+ MainViewModel.java
59
+ ```java
60
+ import androidx.lifecycle.*;
61
+
62
+ public class MainViewModel extends ViewModel {
63
+ private MutableLiveData<MainActivity.Transfer> transferLiveData = new MutableLiveData<>();
64
+ LiveData<MainActivity.Transfer> getTransfer() {
65
+ return transferLiveData;
66
+ }
67
+ void setTransfer(MainActivity.Transfer transfer) {
68
+ transferLiveData.setValue(transfer);
69
+ }
70
+
71
+ private MutableLiveData<String> telegramErrorCodeLiveData = new MutableLiveData<>();
72
+ LiveData<String> getTelegramErrorCode() {
73
+ return telegramErrorCodeLiveData;
74
+ }
75
+
76
+ void startThread() {
77
+ new Thread(
78
+ () -> {
79
+ try {
80
+ Thread.sleep(3 * 1000); //[ms]
81
+ } catch(InterruptedException e) {
82
+ telegramErrorCodeLiveData.postValue("B8");
83
+ return;
84
+ }
85
+ telegramErrorCodeLiveData.postValue("ABCDEF");
86
+ }
87
+ ).start();
88
+ }
89
+ }
90
+ ```
91
+ AlertDialogFragment.java
92
+ ```java
93
+ import android.app.Dialog;
94
+ import android.content.Context;
95
+ import android.os.Bundle;
96
+
97
+ import androidx.annotation.*;
98
+ import androidx.appcompat.app.AlertDialog;
99
+ import androidx.fragment.app.DialogFragment;
100
+
101
+ public class AlertDialogFragment extends DialogFragment {
102
+ static DialogFragment getInstance(String errorCode) {
103
+ if(errorCode == null || errorCode.length() == 0) return null;
104
+
105
+ DialogFragment df = new AlertDialogFragment();
106
+ Bundle args = new Bundle();
107
+ args.putString("ErrorCode", errorCode);
108
+ df.setArguments(args);
109
+ return df;
110
+ }
111
+
112
+ @NonNull
113
+ @Override
114
+ public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
115
+ String errorCode = requireArguments().getString("ErrorCode", null);
116
+ FileUtils.outputLogFile(getContext(), Constants.LOG_ALERT, "伝文エラー:" + errorCode, null);
117
+
118
+ // タイトルとメッセージの生成
119
+ String title, message;
120
+ if (errorCode.equals("B8")) { //「B8」エラーの場合のみ異なるメッセージを出す
121
+ title = "登録エラー";
122
+ message = "予約を完了する事が出来ませんでした";
123
+ } else {
124
+ title = getString(R.string.confirm_telegram_error_title);
125
+ message = getString(R.string.confirm_telegram_message) + "\nエラーコード:" + errorCode;
126
+ }
127
+
128
+ setCancelable(false); //false でダイアログ外のタッチやバック操作でのダイアログのキャンセルを出来なくする.
129
+
130
+ return new AlertDialog.Builder(requireActivity())
131
+ .setTitle(title)
132
+ .setMessage(message)
133
+ .setPositiveButton("閉じる", (d, w) -> {})
134
+ .create();
135
+ }
136
+ }
137
+
138
+ //テスト用ダミー
139
+ enum Constants {
140
+ LOG_ALERT
141
+ }
142
+ class FileUtils {
143
+ static void outputLogFile(Context context, Constants constants, String contents, Object obj) {}
144
+ }
145
+ ```
146
+ AFragment.java
147
+ ```java
148
+ import android.os.Bundle;
149
+ import android.view.View;
150
+ import android.widget.Button;
151
+
152
+ import androidx.annotation.*;
153
+ import androidx.fragment.app.Fragment;
154
+ import androidx.lifecycle.ViewModelProvider;
155
+
156
+ public class AFragment extends Fragment {
157
+ public AFragment() {
158
+ super(R.layout.fragment_a);
159
+ }
160
+
161
+ @Override
162
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
163
+ super.onViewCreated(view, savedInstanceState);
164
+
165
+ MainViewModel model = new ViewModelProvider(requireActivity()).get(MainViewModel.class);
166
+
167
+ Button toB = view.findViewById(R.id.toB_button);
168
+ toB.setOnClickListener(v -> model.setTransfer(MainActivity.Transfer.B));
169
+ }
170
+ }
171
+ ```
172
+ layout/fragment_a.xml
173
+ ```xml
174
+ <?xml version="1.0" encoding="utf-8"?>
175
+ <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
176
+ xmlns:app="http://schemas.android.com/apk/res-auto"
177
+ xmlns:tools="http://schemas.android.com/tools"
178
+ android:layout_width="match_parent"
179
+ android:layout_height="match_parent"
180
+ android:background="#ffc0c0"
181
+ tools:context=".AFragment">
182
+
183
+ <TextView
184
+ android:id="@+id/text"
185
+ android:layout_width="wrap_content"
186
+ android:layout_height="wrap_content"
187
+ android:text="A"
188
+ android:textSize="50dp"
189
+ app:layout_constraintBottom_toBottomOf="parent"
190
+ app:layout_constraintEnd_toEndOf="parent"
191
+ app:layout_constraintStart_toStartOf="parent"
192
+ app:layout_constraintTop_toTopOf="parent" />
193
+ <Button
194
+ android:id="@+id/toB_button"
195
+ android:layout_width="wrap_content"
196
+ android:layout_height="wrap_content"
197
+ android:text="to B"
198
+ app:layout_constraintBottom_toBottomOf="parent"
199
+ app:layout_constraintEnd_toEndOf="parent"
200
+ app:layout_constraintStart_toStartOf="parent"
201
+ app:layout_constraintTop_toBottomOf="@id/text" />
202
+ </androidx.constraintlayout.widget.ConstraintLayout>
203
+ ```
204
+ BFragment.java
205
+ ```java
206
+ import android.os.Bundle;
207
+ import android.view.View;
208
+ import android.widget.Button;
209
+
210
+ import androidx.annotation.*;
211
+ import androidx.fragment.app.Fragment;
212
+ import androidx.lifecycle.ViewModelProvider;
213
+
214
+ public class BFragment extends Fragment {
215
+ public BFragment() {
216
+ super(R.layout.fragment_b);
217
+ }
218
+
219
+ @Override
220
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
221
+ super.onViewCreated(view, savedInstanceState);
222
+
223
+ MainViewModel model = new ViewModelProvider(requireActivity()).get(MainViewModel.class);
224
+
225
+ Button threadButton = view.findViewById(R.id.thread_button);
226
+ threadButton.setOnClickListener(v -> {
227
+ model.startThread();
228
+ model.setTransfer(MainActivity.Transfer.A);
229
+ });
230
+ }
231
+ }
232
+ ```
233
+ layout/fragment_b.xml
234
+ ```xml
235
+ <?xml version="1.0" encoding="utf-8"?>
236
+ <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
237
+ xmlns:app="http://schemas.android.com/apk/res-auto"
238
+ xmlns:tools="http://schemas.android.com/tools"
239
+ android:layout_width="match_parent"
240
+ android:layout_height="match_parent"
241
+ android:background="#80ffff"
242
+ tools:context=".BFragment">
243
+
244
+ <TextView
245
+ android:id="@+id/text"
246
+ android:layout_width="wrap_content"
247
+ android:layout_height="wrap_content"
248
+ android:text="B"
249
+ android:textSize="50dp"
250
+ app:layout_constraintBottom_toBottomOf="parent"
251
+ app:layout_constraintEnd_toEndOf="parent"
252
+ app:layout_constraintStart_toStartOf="parent"
253
+ app:layout_constraintTop_toTopOf="parent" />
254
+ <Button
255
+ android:id="@+id/thread_button"
256
+ android:layout_width="wrap_content"
257
+ android:layout_height="wrap_content"
258
+ android:text="thread"
259
+ app:layout_constraintBottom_toBottomOf="parent"
260
+ app:layout_constraintEnd_toEndOf="parent"
261
+ app:layout_constraintStart_toStartOf="parent"
262
+ app:layout_constraintTop_toBottomOf="@id/text" />
263
+ </androidx.constraintlayout.widget.ConstraintLayout>
264
+ ```

2

追加

2024/10/24 15:58

投稿

jimbe
jimbe

スコア13170

test CHANGED
@@ -1,3 +1,4 @@
1
1
  複数のアクティビティ間で処理をアレコレすることはとても面倒くさく、またOSにもそこそこ負担です。
2
2
  (質問ではBからAへの遷移が常に成功する前提のようですが、遷移した瞬間にAが居なくなる可能性もあります。)
3
3
  アクティビティをアプリで1つだけとし、各画面をフラグメントで構成してフラグメントを入れ換えることで画面遷移を実現すれば、悩まずに済むと思います。
4
+ (ついでに、ダイアログもそのまま使うとアクティビティが再生成されたときにダイアログは再生成されません。ダイアログフラグメントを使うと再生成されます。)

1

追加

2024/10/24 15:37

投稿

jimbe
jimbe

スコア13170

test CHANGED
@@ -1,2 +1,3 @@
1
1
  複数のアクティビティ間で処理をアレコレすることはとても面倒くさく、またOSにもそこそこ負担です。
2
+ (質問ではBからAへの遷移が常に成功する前提のようですが、遷移した瞬間にAが居なくなる可能性もあります。)
2
3
  アクティビティをアプリで1つだけとし、各画面をフラグメントで構成してフラグメントを入れ換えることで画面遷移を実現すれば、悩まずに済むと思います。