web-dev-qa-db-ja.com

DialogFragmentからのアクティビティの管理

DialogFragmentを作成したアクティビティからfinish()およびその他の非静的メソッドを呼び出すにはどうすればよいですか? DialogFragmentのOnClickLisenerからメッセージを渡そうとしましたが、役に立ちませんでした。

MainActivityとDialogFragmentで構成される非常にシンプルなアプリがあります。

    public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle arg0) {
    super.onCreate(arg0);
    setContentView(R.layout.activity);
    showDialog();
}
public void showDialog() {
    DialogFragment newFragment = new ConfirmDialog();
    newFragment.show(getFragmentManager(), "dialog");
}

そして、ダイアログも非常にシンプルです。

public class ConfirmDialog extends DialogFragment {
@Override
public AlertDialog onCreateDialog(Bundle savedInstanceState) {
    // Use the Builder class for convenient dialog construction
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    builder.setMessage("Confirm you want to continue?")
           .setPositiveButton("Yes.", new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                   //finish() MainActvity
                  }
               })
           .setNegativeButton("No.", new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                 //Do nothing in MainActity
               }
           });
    // Create the AlertDialog object and return it
    return builder.create();
}

}

14
Hennaz

多くのオプションがあります。それらの1つは、内部に単一のメソッドを持つインターフェースを定義することです。

  1. ダイアログの呼び出し元にそのインターフェイスを実装してもらいます。
  2. 呼び出し元を指すグローバル変数を保持します。
  3. onAttach(Activity activity)メソッドで変数を設定します。
  4. onDetach()メソッドでその変数をnullにします。
  5. onClickの変数(インターフェイスメンバー)メソッドを呼び出します。

例:

_public class MainActivity extends Activity implements MyInterface { 
    // ...

    @Override
    public void onChoose() { finish(); }

}
_

そしてConfirmDialogの内部:

_public static interface MyInterface {
    public void onChoose();
}

private MyInterface mListener;

@Override
public void onAttach(Activity activity) {
    mListener = (MyInterface) activity;
    super.onAttach(activity);
}

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

次に、クラス内の任意の場所でmListener.onChoose()を呼び出します。


これが承認済みとしてマークされていることは知っていますが、ディスカッションにさらにフィードバックを提供できると思いました。

またはnotインターフェースの使用に関する注意。アンディの答えは私のと同じようにrightとして機能するので、なぜ私はと言ったのですか?「多くのオプションがあります。そのうちの1つは...」

ただし、この特定の問題にインターフェイスを使用する理由は、ほとんどの場合、そのような単純な/一般的な確認ダイアログを拡張して再利用するためです。ちょっと一般的すぎて「無駄」にはなりません(さらに悪いことに、異なるイベントアクションが発生した場合は重複します)。

それを1回だけ使用することに致命的な確信がない限り、1つの目的(終了)のために、通常、ダイアログクラスのActivityの実装の詳細をハードワイヤリング(および単純化)することは避けてください。 柔軟性、抽象化、効率。維持するコードが少なくて済みます。

そして、はい、あなたがそれを必要とするかもしれないtelltaleがあります:あなたが使用しているpublicキーワード、特にそれが再利用を要求する自己完結型のクラスファイル(あまりにも)。それ以外の場合は、実装の詳細がそのクラスにのみ関連するため、メインのActivity内にそのクラスを非表示にする必要があります。また、publicキーワードを削除することになります。

はい、複数のActivityに使用できますが、finish() ingに制限されます。このインターフェースにより、各Activityで必要なことを柔軟に実行できます。言い換えると、そのイベントに対してそれ自体がどのように動作するかを定義するのは実装者次第です。実装の詳細は自己完結型です。

補足として、私がしていることは、アプリケーションに必要なすべてのダイアログを含むパッケージを作成することです。そのような確認ダイアログのために、私はさまざまなメッセージやボタンに再利用します。デフォルトを提供しますが、setArgumentsを使用して変更することもできます。また、インターフェイスを関連付けたままにしているので、ダイアログごとに1つのインターフェイスを作成する必要はありません。実装者は、どのダイアログが「ダイアログコールバック」をトリガーしたかに従って応答します。柔軟性、抽象化、効率性、そしてユーモラスに呼ばれるものを避けながら Hydra and Royal Family 。そう。結局、私が言ったように、多くのオプションがあります。過度に設計しないでください。ただし、単純化しすぎないようにしてください(適切な拡張の余地を残してください)。

これまたは他の答えを選択するよりも、利点と落とし穴を理解することが重要です。

28
davidcesarino

インターフェイスの作成に必要な作業量は少ないですが、インターフェイスを作成したアクティビティからfinish()を呼び出す必要がある理由がわかりません。 DialogFragment自体の中からfinish()を呼び出すだけで十分です。何らかの理由で情報を送り返す必要がある場合は、いつでもgetActivity()を呼び出して、アクティビティに存在するメソッドをチェーンすることができます。最終的には、どこで終了と呼んでも、フラグメントを切り離して破壊します。

フラグメント内のアクティビティからメソッドを呼び出す方法を明確にするためだけに

((YourActivity)getActivity()).someMethod(param);

Javaは、Activityに呼び出したいメソッドがあることを知らないため、カーストする必要があります。どちらの方法を選択しても、幸運を祈ります:)

乾杯

[〜#〜]編集[〜#〜]

デビッドの説明に感謝します。一般的にあなたは正しいです。しかし、この場合、正直に言うと、フラグメントの性質とアクティビティとの関係のために、あなたは正しくありません。繰り返しになりますが、基本的には、保持されているActivityクラスと非常に密接な関係にあるフラグメントによって呼び出されるリスナーを作成します。 この場合、リスナーを介して何も配線しないことによって提供される利点はすべて失われます。ダイアログごとにカスタムコードを書き直すことになります。私のメソッドでは、Activityクラスにメソッドを書くことができるので、一度だけ書く必要があります。

リスナーを使用する必要があると思う理由は2つだけです。

1。他の人が使用するコードを書いている場合。したがって、特定の構造(AndroidのDatePickerDialogなど)を維持しながら情報を提供する簡単な方法を提供します。

2。接続を維持しようとしている2つの部分の間に接続がない場合(JavaのGUIのように)。

ですから、私はデビッドがこれを間違っていると言っているのではなく、人々がいつそれらを使用するかを理解することが重要であるため、彼がそれを提起してくれたことに感謝しています。しかし、この場合も、フラグメントとアクティビティクラスが関連しているため、彼が言及する利点は存在しません。ここでリスナーが必要ないと私が信じる理由を明らかにしたかっただけです。

21
Andy

の代わりに:

.setPositiveButton("Yes.", new DialogInterface.OnClickListener() { 
    public void onClick(DialogInterface dialog, int id) { 
        //finish() MainActvity
    }
})

使用する:

.setPositiveButton("Yes.", new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int id) { 
        // this gets the current activity.              
        Activity currentActivity = getActivity();
        // this finish() method ends the current activity.
        currentActivity.finish(); 
    }
})
0
Moses Katsina

これはおそらく最善の方法ではありませんが、機能します。アクティビティの参照の作成で、startActivityとfinishを呼び出す静的メソッドを作成し、「OK」の場合はダイアログからこの静的メソッドを呼び出します。以下のコード:

private static Activity mActivity = null;
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mActivity = this;
}

public static void staticMethodToCall(){
         Intent intent = new Intent(mActivity,Second.class);
         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         mActivity.startActivity(intent);
         mActivity.finish();
    }

そしてダイアログボックスで

 builder.setMessage("Confirm you want to continue?")
           .setPositiveButton("Yes.", new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {

                   TheClassWithTheStaticMetod.staticMethodToCall();
                  }
               })
0
Mikelis Kaneps