Android Fragmentsのリファレンス(特に DialogFragment ))で、私が期待するものとは異なるいくつかのことを行うことに気付きました:
1)。コンストラクタではなくpublic static foo newInstance()
メソッドを使用します。
2)。メンバー変数ではなくsetArgumentsを使用して、onCreateDialogに値を渡します。
リフレクションを使用する場合、newInstanceの方が好ましいように見えることを読みました。しかし、なぜそれらがバンドルを介してパラメーターを渡すのか本当に理解していません。ただし、メンバー変数を使用するほうが安全で(マップからフェッチするために文字列を使用しない)、オーバーヘッドが少なくなります。
何かご意見は?
私もこれに遭遇し、インスタンスフィールドよりも引数Bundle
を使用することのいくつかの利点を見つけました:
Bundle
にある場合、Androidシステムはそれを認識しており、Fragment
を作成および破棄できます(必須のパラメーターなし/デフォルトコンストラクターと通常のライフサイクルメソッドを使用) 、そして引数バンドルをもう一度渡すだけです。このようにして、低メモリ破壊の傾向や最終的な向きの変更によって引数が失われることはありません(これは、回転の少ないエミュレータでの開発後、実際のデバイスに最初に展開するときにしばしば私に当たります)。
Bundle
のエクストラActivity
をそのままレイアウトに埋め込まれたFragment
に渡すことができます。例えばActivity
"フルスクリーン"を表示するFragment
があり、何を表示/実行するかを知るためにいくつかのID(またはContentProvider
URI)が必要な場合、これをよく使用します。渡す前にBundle
(またはコピー)にデータを追加することさえあります。
_@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) { // not a re-creation
final Bundle args = new Bundle(getIntent().getExtras());
args.putInt(CoverImageFragment.BACKGROUND_RESOURCE, Android.R.color.black);
final Fragment fragment = CoverImageFragment.newInstance(args);
getSupportFragmentManager()
.beginTransaction()
.add(Android.R.id.content, fragment)
.commit();
}
}
_
Fragment
の開発方法をActivity
の開発方法に近づけます。つまり、Bundle
を「入力パラメーター、例外なし」として作成します。
あなたが言及した欠点については:
タイトなループでBundle
をクエリすることはほとんどないため、オーバーヘッドは最小限であると思います。そのため、onCreate()
、onViewCreate()
で引数データを一度取得します。などはそれほど悪くありません。
タイプセーフのために、Bundle
にはさまざまなgetXXXX()
メソッドがすべてあります。また、何かが欠けている場合やオプションの場合は、オーバーロードしてデフォルト値を提供することもできます。
newInstance()
メソッドについては、new
およびsetArguments()
の呼び出しをFragment
にカプセル化する簡単な方法と考えています。 Bundle
とFragment
の両方を一度に作成して、すぐに使えるFragment
インスタンスを返す追加のMyFragment newInstance(String singleIdOfWhatToDisplay)
を提供することがあります。
これは非常に混乱する問題であることがわかりました(Androidランドスケープ)を散らかす多くの問題の1つ)。
setArguments()
は、Fragmentsでパラメーターなしのコンストラクターを使用できるようにするというAndroidの非常に役に立たないニーズに対する回避策です。
私の混乱は波に包まれました。まず、Fragment
で自然にオーバーライドするメソッド(例:onCreate
、onCreateView
)は、Bundle
のを表すsavedInstanceState
パラメータを受け取ります。あなたのFragment
。このインスタンスの状態には、明らかに[〜#〜] nothing [〜#〜]を使用して、setArguments()
を介して保存し、getArguments()
を介して取得する値をどのように処理してもかまいません。どちらもBundle
を使用し、両方のBundles
は同じオーバーライドされたメソッド内でアクセスされる可能性が高く、どちらも相互に関係ありません。
次に、AndroidがsetArguments()
を使用する方法が不明です。Androidは、パラメータなしのコンストラクタを呼び出してFragment
を再構築します回転しますが、Fragment
が作成されたときに最後に呼び出されたsetArguments()
メソッドを呼び出します。
え?
すばらしいですが、本当です。パラメータなしのBundles
コンストラクタの必要性を補うために、これらすべてがsetArguments()
狂気でFragment
を作成しています。
つまり、静的なnewInstance
メソッドを使用してFragment
を作成しています。
public MyFragment() {
//satisfy Android
}
public static MyFragment newInstance(long record_id) {
Log.d("MyFragment", "Putting " + record_id + " into newInstance");
MyFragment f = new MyFragment();
Bundle args = new Bundle();
args.putLong("record_id", record_id);
f.setArguments(args);
return f;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/**
* Perform an immediate check of arguments,
* which ARE NOT the same as the bundle used
* for saved instance state.
*/
Bundle args = getArguments();
if(args != null) {
record_id = args.getLong("record_id");
Log.d("MyFragment", "found record_id of " + String.valueOf(record_id));
}
if(savedInstanceState != null) {
//now do something with savedInstanceState
}
}
私はAndroidプログラミングにかなり慣れていますが、これは問題に対する私の現在の理解です:
フラグメントのコンストラクタcannotにはパラメータがあります。アクティビティが一時停止すると、フラグメントを解放できます。アクティビティが再開される前に、システムはコンストラクターを呼び出すフラグメントの新しいバージョンを作成します。デフォルト以外のコンストラクタが使用されている場合、AndroidはFragmentsコンストラクタへの引数のタイプと値が何であるかを知っているはずですか?
バンドルがリリースされたとは思いません。バンドルは正確に保持されるため、デフォルトのコンストラクターで再作成された後、フラグメントに戻すことができます。
Philipp Reichartは彼の投稿でこれを回避しました(実際には回避された以上です)。
引数にもう1つ欠点を追加したいのは、動的にフラグメントを作成する必要があることです。 xmlから作成した場合、引数はあまり機能しません。そして私はそれが本当に嫌いです。