58

我最近厌倦了StringBundles创建我的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,这似乎和我的构造函数一样。所以我自己做了一个测试,它和以前一样完美无瑕,除了 Lint 抱怨它。

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 不会抱怨它。所以基本上我的问题是,为什么谷歌不希望你使用带参数的构造函数 for Fragments

我唯一的猜测是,您不要尝试在不使用 的情况下设置实例变量Bundle,重新创建时不会设置该变量Fragment。通过使用static newInstance()方法,编译器不会让您访问实例变量。

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

    mImageResourceId = imageResourceId;
}

我仍然觉得这不足以成为禁止在构造函数中使用参数的充分理由。其他人对此有见解吗?

4

2 回答 2

64

我个人发现使用构造函数比知道使用 newInstance() 和传递参数要普遍得多。

工厂方法模式在现代软件开发中相当频繁地使用。

所以基本上我的问题是,为什么谷歌不希望你使用带有参数的构造函数来处理片段?

你是在自问自答:

我唯一的猜测是,您不要尝试在不使用 Bundle 的情况下设置实例变量,在重新创建 Fragment 时不会设置该实例变量。

正确的。

我仍然觉得这不足以成为禁止在构造函数中使用参数的充分理由。

欢迎您发表意见。欢迎您在每个构造函数或每个工作空间的方式上禁用此 Lint 检查。

于 2013-02-01T21:03:17.430 回答
2

Android 仅使用默认构造函数重新创建它杀死的片段,因此我们在其他构造函数中所做的任何初始化都将丢失。因此数据将丢失。

于 2016-07-08T11:38:20.450 回答