@yydlは、newInstance
メソッドが優れている理由について説得力のある理由を示していますが、
Androidが後でフラグメントを再作成することを決定した場合、フラグメントの引数のないコンストラクターを呼び出します。そのため、コンストラクターのオーバーロードは解決策ではありません。
コンストラクタを使用することは依然として可能です。これがなぜかを確認するには、まず、上記の回避策がAndroidで使用される理由を確認する必要があります。
フラグメントを使用する前に、インスタンスが必要です。AndroidはYourFragment()
(引数なしのコンストラクター)を呼び出して、フラグメントのインスタンスを作成します。ここでは、Androidがどちらを使用するかを認識できないため、オーバーロードしたコンストラクターは無視されます。
アクティビティの存続期間中に、フラグメントは上記のように作成され、Androidによって複数回破棄されます。つまり、フラグメントオブジェクト自体にデータを配置した場合、フラグメントが破棄されるとデータは失われます。
回避策として、AndroidはBundle
(呼び出しsetArguments()
)を使用してデータを保存するように要求しますYourFragment
。これは、からアクセスできます。引数bundle
はAndroidによって保護されているため、永続的であることが保証されています。
このバンドルを設定する1つの方法は、静的newInstance
メソッドを使用することです。
public static YourFragment newInstance (int data) {
YourFragment yf = new YourFragment()
/* See this code gets executed immediately on your object construction */
Bundle args = new Bundle();
args.putInt("data", data);
yf.setArguments(args);
return yf;
}
ただし、コンストラクタ:
public YourFragment(int data) {
Bundle args = new Bundle();
args.putInt("data", data);
setArguments(args);
}
newInstance
メソッドとまったく同じことができます。
当然、これは失敗し、AndroidがこのnewInstance
メソッドを使用してほしい理由の1つです。
public YourFragment(int data) {
this.data = data; // Don't do this
}
さらに説明すると、Androidのフラグメントクラスは次のとおりです。
/**
* Supply the construction arguments for this fragment. This can only
* be called before the fragment has been attached to its activity; that
* is, you should call it immediately after constructing the fragment. The
* arguments supplied here will be retained across fragment destroy and
* creation.
*/
public void setArguments(Bundle args) {
if (mIndex >= 0) {
throw new IllegalStateException("Fragment already active");
}
mArguments = args;
}
Androidは、引数が構築時にのみ設定されることを要求し、これらが保持されることを保証することに注意してください。
編集:@JHHのコメントで指摘されているように、引数を必要とするカスタムコンストラクターを提供している場合、Javaは引数のないデフォルトコンストラクターをフラグメントに提供しません。したがって、これには引数なしのコンストラクタを定義する必要があります。これは、newInstance
ファクトリメソッドで回避できるコードです。
編集:Androidはフラグメントにオーバーロードされたコンストラクターを使用することを許可しなくなりました。newInstance
メソッドを使用する必要があります。