フラグメントのデフォルト以外のコンストラクターを避けたいのはなぜですか?


173

私はFragmentsそれらの1つでデフォルト以外のコンストラクタを作成してこの警告を得たアプリを作成しています:

Avoid non-default constructors in fragments: use a default constructor plus Fragment#setArguments(Bundle) instead

なぜこれが良い考えではないのか誰かに教えてもらえますか?

私がこれを達成する方法を提案することもできます:

public static class MenuFragment extends ListFragment {
    public ListView listView1;
    Categories category;

    //this is my "non-default" constructor
    public MenuFragment(Categories category){
        this.category = category;
    }....

デフォルト以外のコンストラクタを使用せずに?



3
いいえ、それらは役に立ちません。彼らは私の質問に答えませんでした。しかし、それでもなおありがとう:)
BlackHatSamurai 2012

31
@BlaineOmega実際にこれは特に:stackoverflow.com/a/11602478/321697は間違いなくあなたの質問に答えます。Fragmentが再作成される原因となる向きの変更やその他のイベントでは、Androidはデフォルトのコンストラクターと引数として渡されたバンドルを使用します。カスタムコンストラクターを使用している場合、これらのイベントのいずれかが原因でフラグメントが再作成されるとすぐに、カスタムコンストラクターで行った操作はすべて失われます。
Kevin Coppock

1
ありがとう、しかしそれは理由に答えますが、方法には答えません。
BlackHatSamurai

それは私の最初のコメントの最初と2番目のリンクでカバーされています。
CommonsWare 2012

回答:


110

バンドルオブジェクトを作成し、データ(この例ではCategoryオブジェクト)を挿入します。シリアル化可能でない限り、このオブジェクトをバンドルに直接渡すことはできません。フラグメントでオブジェクトを構築し、IDか何かだけをバンドルに入れる方が良いと思います。これは、バンドルを作成してアタッチするためのコードです。

Bundle args = new Bundle();
args.putLong("key", value);
yourFragment.setArguments(args);

その後、フラグメントアクセスデータで:

Type value = getArguments().getType("key");

それで全部です。


3
オブジェクトを渡す方法は?Context Objectまたはその他のオブジェクトを渡したいのですが。
アディルマリク

12
バンドルは、シリアル化されたJavaオブジェクトとオブジェクトを運ぶことができParcelableます。また、ContextフラグメントのgetActivity()メソッドを介して情報にアクセスできるため、を渡さないでください。
クラカトア2013

これをどこで行うのType value = getArguments().getType("key");か?
ムハンマドババール2013年

4
@Muhammad Babar:私があなたなら、それをnewInstance()メソッドに追加します。例:public static FragmentName newInstance(your variables){}。Androidのドキュメントで推奨されているように、パラメーターを使用してコンストラクターを作成しないでください。デフォルトのパラメーター(パラメーターなし)は、フラグメントの再起動後に自動的に呼び出されます。
nistv4n 2013年

@MuhammadBabar onCreateViewは問題あり
ません

272

「デフォルトのコンストラクタではなく、パラメータを渡すためになぜバンドルを使用するのか」という答えは実際には何も答えていないようです

バンドルを介してパラメータを渡す必要があるのは、システムがを復元するときfragment(たとえば、構成の変更時)、自動的にが復元されるためbundleです。

コールバックは、からパラメータを読み取るonCreateか、またはonCreateViewパラメータを読み取る必要がありますbundle-このようにして、fragment正しく状態fragmentを初期化されたときと同じ状態に戻すことが保証されます(この状態onSaveInstanceState bundleは、に渡されるとは異なる場合がありますonCreate/onCreateView

静的newInstance()メソッドを使用することの推奨は、単なる推奨です。デフォルト以外のコンストラクタを使用できますが、bundleそのコンストラクタの本体の内部に初期化パラメータを入力してください。onCreate()またはこれらのパラメーターをまたはonCreateView()メソッドで読み取ります。


2
よく説明しました。ありがとう。私が質問した人なら、私はあなたにカチカチを与えただろう
Karue Benson Karue

5
(何らかの理由で)デフォルト以外のコンストラクタを使用することはできなくなりました...コンパイラエラーが発生します(以前は警告でした)。
MPavlak

51

あなたのFragmentためにどのようにコンストラクタ持つべきではないFragmentManager、それをインスタンス化します。あなたは持っている必要がありnewInstance()、必要なパラメータで定義された静的メソッドをし、それらをバンドルしているとのことができます後でアクセス、フラグメントの引数として、それらを設定するBundleパラメータです。

例えば:

public static MyFragment newInstance(int title, String message) {
    MyFragment fragment = new MyFragment();
    Bundle bundle = new Bundle(2);
    bundle.putInt(EXTRA_TITLE, title);
    bundle.putString(EXTRA_MESSAGE, message);
    fragment.setArguments(bundle);
    return fragment ;
}

そして、これらの引数をで読んでくださいonCreate

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    title = getArguments().getInt(EXTRA_TITLE);
    message = getArguments().getString(EXTRA_MESSAGE);

    //...
}

このように、デタッチされて再アタッチされた場合、オブジェクトの状態はbundlesIntentsにアタッチされた場合と同様に、引数を介して保存できます。


9

一部のクラスでパラメータを使用する場合。これを試して

SomeClass mSomeInstance;
public static final MyFragment newInstance(SomeClass someInstance){
    MyFragment f = new MyFragment();
    f.mSomeInstance = someInstance;
    return f;
}

5
これは実際には悪い提案です。Fragmentがによって再作成されるとFragmentManager、mSomeInstanceが失われます。
Yaroslav Mytkalyk 2016年

そうですね、SomeClassはパーセル化可能で、setArguments()を使用してバンドルに格納する必要があります
Jake_

1

静的コンストラクターと2つのコンストラクター(引数をFragmentの引数バンドルに格納する空のパラメーター化されたコンストラクター)の間に違いはないと思います。おそらく、この経験則は、Javaで引数なしのコンストラクターの実装を忘れる確率を減らすために作成されますオーバーロードが存在する場合、暗黙的に生成されません。

私のプロジェクトでは、Kotlinを使用し、引数なしのプライマリコンストラクターとセカンダリコンストラクターを使用してフラグメントを実装し、それらをバンドルに格納してフラグメント引数として設定するだけで、すべてが正常に機能します。


0

構成の変更後にフラグメントがデフォルト以外のコンストラクターを使用する場合、フラグメントはすべてのデータを失います。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.