web-dev-qa-db-ja.com

フラグメントの作成:コンストラクターvs newInstance()

最近、Stringを作成するときにBundlesに引数を渡すためにFragmentsキーを常に知る必要があることにうんざりしました。そこで、設定したいパラメーターを取るFragmentsのコンストラクターを作成し、それらの変数を正しいBundlesキーでStringに入れて、他のFragmentsActivitiesがこれらのキーを知る必要がある。

_public ImageRotatorFragment() {
    super();
    Log.v(TAG, "ImageRotatorFragment()");
}

public ImageRotatorFragment(int imageResourceId) {
    Log.v(TAG, "ImageRotatorFragment(int imageResourceId)");

    // Get arguments passed in, if any
    Bundle args = getArguments();
    if (args == null) {
        args = new Bundle();
    }
    // Add parameters to the argument bundle
    args.putInt(KEY_ARG_IMAGE_RES_ID, imageResourceId);
    setArguments(args);
}
_

そして、それらの引数を通常のように引き出します。

_@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Log.v(TAG, "onCreate");

    // Set incoming parameters
    Bundle args = getArguments();
    if (args != null) {
        mImageResourceId = args.getInt(KEY_ARG_IMAGE_RES_ID, StaticData.getImageIds()[0]);
    }
    else {
        // Default image resource to the first image
        mImageResourceId = StaticData.getImageIds()[0];
    }
}
_

しかし、Lintはこれに問題を抱えており、Fragmentのサブクラスに他のパラメーターを持つコンストラクターがないことを指摘し、アプリを実行するために@SuppressLint("ValidFragment")を使用する必要がありました。事は、このコードは完全に問題なく動作するということです。 ImageRotatorFragment(int imageResourceId)または古い学校のメソッドImageRotatorFragment()を使用して、setArguments()を手動で呼び出すことができます。 Android Fragment(向きの変更またはメモリ不足)を再作成する必要がある場合、ImageRotatorFragment()コンストラクターを呼び出し、同じ引数Bundleを自分の値で渡します。 、正しく設定されます。

だから私は「提案された」アプローチを探しており、newInstance()を使用してパラメータを持つFragmentsを作成する多くの例を見てきました。これは私のコンストラクタと同じことをしているようです。それで、私はそれをテストするために私自身を作りました、そして、それは以前と同じように完璧に動作します。

_public static ImageRotatorFragment newInstance(int imageResourceId) {
    Log.v(TAG, "newInstance(int imageResourceId)");

    ImageRotatorFragment imageRotatorFragment = new ImageRotatorFragment();

    // Get arguments passed in, if any
    Bundle args = imageRotatorFragment.getArguments();
    if (args == null) {
        args = new Bundle();
    }
    // Add parameters to the argument bundle
    args.putInt(KEY_ARG_IMAGE_RES_ID, imageResourceId);
    imageRotatorFragment.setArguments(args);

    return imageRotatorFragment;
}
_

個人的には、コンストラクターを使用することは、newInstance()を使用してパラメーターを渡すことを知っているよりもはるかに一般的な方法であることがわかります。この同じコンストラクターテクニックをアクティビティで使用でき、Lintが文句を言うことはないと思います。 つまり、基本的に私の質問は、GoogleがFragmentsのパラメーターを持つコンストラクターを使用することを望まない理由です

私の唯一の推測は、Bundleを再作成しても設定されないFragmentを使用せずにインスタンス変数を設定しようとしないことです。 static newInstance()メソッドを使用すると、コンパイラーはインスタンス変数にアクセスできなくなります。

_public ImageRotatorFragment(int imageResourceId) {
    Log.v(TAG, "ImageRotatorFragment(int imageResourceId)");

    mImageResourceId = imageResourceId;
}
_

私はまだ、これがコンストラクターでのパラメーターの使用を禁止する十分な理由であるとは思わない。他の誰かがこれに洞察力を持っていますか?

54
Steven Byle

個人的には、コンストラクターを使用することは、newInstance()を使用してパラメーターを渡すことを知るよりもはるかに一般的な方法であることがわかりました。

factory method pattern は、現代のソフトウェア開発ではかなり頻繁に使用されます。

したがって、基本的に私の質問は、フラグメントのパラメーターを持つコンストラクターを使用したくないのはなぜですか?

あなた自身の質問に答えました:

私の唯一の推測は、バンドルを使用せずにインスタンス変数を設定しようとしないということです。これは、フラグメントが再作成されたときに設定されません。

正しい。

コンストラクターでのパラメーターの使用を禁止する十分な理由はまだないと思います。

あなたの意見を歓迎します。コンストラクタごとまたはワークスペースごとに、このLintチェックを無効にしてください。

60
CommonsWare

Androidは、デフォルトのコンストラクターを使用して削除したフラグメントのみを再作成するため、追加のコンストラクターで行った初期化はすべて失われます。したがって、データは失われます。

0
Jatin Sachdeva