17

ドキュメントを見ると、新しいアラートダイアログフラグメントを初期化するDialogFragment静的メソッドがわかります。newInstance私の質問は、次のようにコンストラクターを使用してそうしないのはなぜかということです。

public MyAlertDialogFragment(int title) {
    Bundle args = new Bundle();
    args.putInt("title", title);
    setArguments(args);
}

これはまったく同じではありませんか、それともどういうわけか違いますか?最善のアプローチとその理由は何ですか?

4

4 に答える 4

28

コンストラクターを介してオブジェクトを受け取る DialogFragment を作成すると、android がフラグメントを再作成するときに問題が発生します。これは何が起こるかです:

  1. コードは、作成したコンストラクターを呼び出し、いくつかの引数を依存関係として渡すダイアログを作成します。
  2. ダイアログが実行され、コンストラクターを介して渡した依存関係が使用されます
  3. ユーザーがアプリを閉じる
  4. 時間が経過し、アンドロイドはフラグメントを強制終了してメモリを解放します
  5. ユーザーがアプリを再度開く
  6. Android は、今回はデフォルトのコンストラクターを使用してダイアログを再作成します。引数は渡されません!
  7. ダイアログは望ましくない状態になります。コンストラクターを通過すると予想されるインスタンス変数を使用しようとする場合がありますが、それらが存在しないため、null ポインター例外が発生します。

これを回避するには、依存関係を確立するためにコンストラクターに依存する必要はありませんが、バンドル (引数と保存されたインスタンス) に依存する必要があります。これにより、一部のクラスで Parcelable を実装する必要が生じる場合がありますが、これは最悪です。

編集: 開発設定で「アクティビティを維持しない」を有効にすることで、アプリを強制終了する Android (ステップ 4) を再現できます。それは簡単にテストする方法です。

于 2014-01-06T15:55:11.130 に答える
20

Android は、Fragments がパブリックで引数のないコンストラクターを持つことに依存しているため、さまざまな時点でそれを再作成できます (たとえば、構成の変更、以前に Android によって強制終了された後のアプリの状態の復元など)。

そのようなコンストラクターがない場合 (例: 問題のコンストラクター)、コンストラクターをインスタンス化しようとすると、次のエラーが表示されます。

Fragment$InstantiationException: Unable to instantiate fragment 
make sure class name exists, is public, and has an empty constructor that is public

によって与えられた引数Fragment.setArguments(Bundle)は保存され、(再) 作成された新しいインスタンスに与えられます。静的メソッドを使用して Fragment を作成すると、引数なしのコンストラクターを維持しながら、必要な引数をセットアップする簡単な方法が提供されます。

于 2012-12-23T14:46:11.107 に答える
11

コンストラクターを でオーバーロードした場合、を再作成する必要があり、パラメーターが渡されない場合MyAlertDialogFragment(int title)、Android システムは引き続きデフォルトのMyAlertDialogFragment()コンストラクターを呼び出す可能性があります。Fragment

于 2012-12-23T14:45:03.030 に答える
4

Android がフラグメントを再作成するときは、常に空のコンストラクターを使用し、 newInstance() を使用して、再作成時にフラグメントが使用するデータを設定できるため (たとえば、画面が回転したとき)

例えば:

   public static FragmentExample newInstance(Parcelable uri) {
    FragmentExample fragmentExample = new FragmentExample();

    Bundle bundle = new Bundle();
    bundle.putParcelable("Uri", uri);
    fragmentExample.setArguments(bundle);

    return fragmentExample;
}
于 2012-12-23T14:44:54.963 に答える