質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

Q&A

解決済

2回答

11894閲覧

Androidのダイアログの表示時のお作法

type23

総合スコア18

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

0グッド

0クリップ

投稿2017/03/31 06:11

編集2017/03/31 09:09

###前提・実現したいこと
相談出来る方が居ないので色々とお作法を教えていだければと思います。
ストレートに言えば、サンプルに示すコードのコードレビューをして頂きたいです。

###疑問点
Androidではダイアログを表示する際にAlertDialogを直接使うのではなく、DialogFragmentを介して表示するのが一般的だと解釈しました。

呼び出し元のActivity(やFragment)側でのイベントの取得が面倒になるような気がしつつ、私なりに解釈した確認ダイアログの実装が下のコードです。

自分で駄目だと思っている点

  • ダイアログを出すトリガーとなる箇所に、閉じたときのリスナーが直接書けないので可読性が悪い。
  • 複数のダイアログを出した場合は、RequestCodeを貰うなど改造して、Positive、Negativeリスナーで処理の振り分けを書かなくてはいけない。
  • 他の種類のダイアログ(アラートダイアログとか)作り、同じAcitivityで呼び出すようになると、もう収集がつかなくなりそう。
  • その他、なんとなく直感的にコードが書けない。

###サンプルで作ったソースコード

java

1public class ManyDialogActivity extends AppCompatActivity implements ConfirmDialogFragment.ConfirmDialogListener { 2 3 @Override 4 protected void onCreate(Bundle savedInstanceState) { 5 super.onCreate(savedInstanceState); 6 setContentView(R.layout.activity_many_dialog); 7 8 Button button1 = (Button) findViewById(R.id.button1); 9 button1.setOnClickListener(new View.OnClickListener() { 10 @Override 11 public void onClick(View v) { 12 ConfirmDialogFragment dialog = ConfirmDialogFragment.newInstance(null, "Aを登録しますが良いですか?"); 13 dialog.show(getSupportFragmentManager(), "TAG"); 14 } 15 }); 16 Button button2 = (Button) findViewById(R.id.button2); 17 button2.setOnClickListener(new View.OnClickListener() { 18 @Override 19 public void onClick(View v) { 20 ConfirmDialogFragment dialog = ConfirmDialogFragment.newInstance(null, "Bを登録しますが良いですか?"); 21 dialog.show(getSupportFragmentManager(), "TAG"); 22 } 23 }); 24 Button button3 = (Button) findViewById(R.id.button3); 25 button3.setOnClickListener(new View.OnClickListener() { 26 @Override 27 public void onClick(View v) { 28 ConfirmDialogFragment dialog = ConfirmDialogFragment.newInstance(null, "Bを登録しますが良いですか?"); 29 dialog.show(getSupportFragmentManager(), "TAG"); 30 } 31 }); 32 } 33 34 @Override 35 public void onClickPositive() { 36 // 引数にRequestCodeのようなものを使って処理を振り分ける? 37 } 38 39 @Override 40 public void onClickNegative() { 41 // 引数にRequestCodeのようなものを使って処理を振り分ける? 42 } 43}

java

1public class ConfirmDialogFragment extends DialogFragment { 2 public static final String TITLE_KEY = ConfirmDialogFragment.class.getName() + ".TITLE_KEY"; 3 public static final String MESSAGE_KEY = ConfirmDialogFragment.class.getName() + ".MESSAGE_KEY"; 4 5 public static ConfirmDialogFragment newInstance(@Nullable String title, String message) { 6 ConfirmDialogFragment fragment = new ConfirmDialogFragment(); 7 Bundle bundle = new Bundle(); 8 bundle.putString(TITLE_KEY, title); 9 bundle.putString(MESSAGE_KEY, message); 10 fragment.setArguments(bundle); 11 return fragment; 12 } 13 14 @NonNull 15 @Override 16 public Dialog onCreateDialog(Bundle savedInstanceState) { 17 Bundle arguments = getArguments(); 18 String title = arguments.getString(TITLE_KEY); 19 String message = arguments.getString(MESSAGE_KEY); 20 21 final Activity activity = getActivity(); 22 AlertDialog.Builder builder = new AlertDialog.Builder(activity) 23 .setTitle(title) 24 .setMessage(message) 25 .setPositiveButton("OK", new DialogInterface.OnClickListener() { 26 @Override 27 public void onClick(DialogInterface dialog, int which) { 28 if (activity instanceof ConfirmDialogListener) { 29 ((ConfirmDialogListener) activity).onClickPositive(); 30 } 31 } 32 } 33 ) 34 .setNegativeButton("キャンセル", new DialogInterface.OnClickListener() { 35 @Override 36 public void onClick(DialogInterface dialog, int which) { 37 if (activity instanceof ConfirmDialogListener) { 38 ((ConfirmDialogListener) activity).onClickNegative(); 39 } 40 } 41 } 42 ); 43 return builder.create(); 44 } 45 46 interface ConfirmDialogListener { 47 void onClickPositive(); 48 49 void onClickNegative(); 50 } 51}

###補足情報(言語/FW/ツール等のバージョンなど)

  • Android4.4 から 7 までが一応の対象バージョンです。
  • サンプルはJavaで掲示しましたが、Kotlinで書いてます。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

Androidは魔境です。
DialogFragmentってあくまでダイアログ風なFragmentなんですよね。。
まぁ使いづらいのでAlertDialogと同じ事できるクラスは用意しておくとある程度楽ですが

コールバック周りはputSerializableとかで上で言うとnewInstance時にリスナー入れたりも一応できますが、回転とか考えると現状のやり方が私はいいかと。
あと個人的にはonAttachでリスナーセットされてるか処理します。

あまりにもリスナー多い場合はidなんか用意したりBundleとうまく向き合います。
なんかActivityResultやBroadCastに慣れるとimplementsが増えるくらい気にしなくなる。。

投稿2017/03/31 09:08

uniko

総合スコア448

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

type23

2017/03/31 09:21

ありがとうございます。 サンプルばかり読んでいて、実際のアプリのコードを読んだことがないので、どれだけ皆さんが苦しんでいるかが分からなかったです。 > Androidは魔境です。 割りとこの一言で救われた気がします。 たかがダイアログを表示して、処理を振り分けるのにここまで苦労するとは思いませんでした。 正直30分もあれば実装できると思ってたのですが、1日がかりです。 みなさんこんなもんなんですか? > コールバック周りはputSerializableとかで上で言うとnewInstance時にリスナー入れたりも一応できますが この手法を最初に考えついたのですが、私の設計が悪いのか、関連する全てのクラスをSerializableにしないといけなくなり、Serializableである必要のないクラスまでSerializableにしなくてはならなくなってしまいました。 > あと個人的にはonAttachでリスナーセットされてるか処理します。 後学のためにこちらの理由を教えて頂けますか? > あまりにもリスナー多い場合はidなんか用意したりBundleとうまく向き合います。 Bundleについての理解が浅いようです。 先の方にもBundleに関してアドバイスを頂きましたが、理解が出来なかったです。 私がもう少し知見を深めなくては話が進まないですね。。。
uniko

2017/03/31 09:30

うーん、とりあえずこちらの端末で動いたけどあっちで動かないとか普通にあるのでまず個人的には安定して動くような方法を重視していますね。ユーザーがどんな操作するか分からないので。。あとSupportLibraryとか更新するだけで落ちたりする場合もあるし。。。 onAttachでリスナーセットは 結局リスナーつけると言う事は返すと言う事なのでコールバックできないと意味ないので。最初についてるか判断してなければなければな処理をしますね。まーあまりないですが例えば不正な呼び出しですよとか。 試してはいませんがこちらの方がソース上げてるみたいですねputSerializable https://gist.github.com/mstssk/7123411
type23

2017/04/03 02:01

遅くなりました。ありがとうございます。 > まーあまりないですが例えば不正な呼び出しですよとか。 今はリスナーをセットしなければ何もしない。という動きにしたかったので、現状のままでも大丈夫そうですね。 参考にあげて頂いたコードも見ました。 最初に思いついた手法でしたが、理解が浅いせいか期待の動きをしなかったので、今の手法を取り入れました。 コードをスッキリさせるためにKotlinで書き始めましたが、動くコードを書くうちに混沌としてきてしましました。。 Androidで製品を作る。というのは想像以上にコストが高いですね。
uniko

2017/04/03 02:17

onAttachについてはライフサイクル的にもActivityに取り付けられた時なのでって意味でやってるとこもありますね。 特別なことすると大変な時もありますが慣れてくればクセもわかってくると思いますよ。
type23

2017/04/04 02:12

ありがとうございます。 なるほど、恐らく誤解してました。 上手く説明が出来ないですが、確かにonAttachでチェックする方が良さそうな気がしてきました。
guest

0

ベストアンサー

■改善点
・onCreateDialogのreturnはbuilderをcreateしたものでは?

■疑問に対する回答

ダイアログを出すトリガーとなる箇所に、閉じたときのリスナーが直接書けないので可読性が悪い。

これは、リスナーをダイアログフラグメント側のフィールドに持つとダイアログフラグメントがシステムから壊された時に復帰できないので現状の実装がベターなのかなと思いますを

複数のダイアログを出した場合は、RequestCodeを貰うなど改造して、Positive、Negativeリスナーで処理の振り分けを書かなくてはいけない。

他の種類のダイアログ(アラートダイアログとか)作り、同じAcitivityで呼び出すようになると、もう収集がつかなくなりそう。

その他、なんとなく直感的にコードが書けない。

これに関してはConfirmDialogListenerの各メソッドの引数にBundleを指定することで備えるといいですね。

投稿2017/03/31 08:25

編集2017/03/31 08:27
yona

総合スコア18155

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

type23

2017/03/31 09:04

ありがとうございます。 ザックリ一言で言えば、今のところこのコードでも悪くない。という認識をもちました。 > ■改善点 > ・onCreateDialogのreturnはbuilderをcreateしたものでは? 失礼しました。ご指摘の通りです。動かしてから貼り付けるべきでした。 > これに関してはConfirmDialogListenerの各メソッドの引数にBundleを指定することで備えるといいですね。 パっと具体的なコードが思いつかなかったのですが、どのような感じでしょうか? ご指摘のイメージから実験コードを書いた方が話が進みやすいかと思いましたが、ちょっと手間取りそうだったので、急ぎ聞かせていただきました。
yona

2017/03/31 09:43

Activityで画面遷移する時にBundleにいろいろなデータを入れてやりとりしますよね? あれと同じことをコールバックインターフェースで行うと、ダイアログクラスが増えてもコールバックインターフェースは1つで済みます。 Bundleに入れる値もしっかりと設計すればある程度保守性は保てるかなと思います。
type23

2017/04/03 01:53

遅くなりました。ありがとうございます。 週末バタバタしてしまい、全く実験が出来なかったです。 > Bundleに入れる値もしっかりと設計すればある程度保守性は保てるかなと思います なるほど。やはりこの辺りはしっかり腰を据えてやらないと難しそうですね。 結局ダイアログを閉じたときにViewをゴニョゴニョしたいことも多く、activity間の結合を疎にしたいと思ったときに、行き当たりばったりだと期待した動きにならず、無駄に労力を費やしてました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問