android - 创建 fragment : constructor vs newInstance()

标签 android constructor android-fragments default-constructor

我最近厌倦了在创建 Fragments 时不断地必须知道 String 键才能将参数传递到 Bundles。所以我决定为我的 Fragments 制作构造函数,它将接受我想要设置的参数,并将这些变量放入具有正确 StringBundles > 键,因此无需其他需要知道这些键的 FragmentsActivity

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() 和传递参数要普遍得多。我相信您可以在 Activity 中使用相同的构造函数技术,并且 Lint 不会提示它。 所以基本上我的问题是,为什么 Google 不希望您为 Fragments 使用带参数的构造函数?

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

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

    mImageResourceId = imageResourceId;
}

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

最佳答案

I personally find that using constructors is a much more common practice than knowing to use newInstance() and passing parameters.

factory method pattern在现代软件开发中相当频繁地使用。

So basically my question is, why does Google not want you to use constructors with parameters for Fragments?

您回答了自己的问题:

My only guess is so you don't try to set an instance variable without using the Bundle, which won't get set when the Fragment gets recreated.

正确。

I still don't feel like this is enough reason to disallow the use of parameters in constructors.

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

关于android - 创建 fragment : constructor vs newInstance(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14654766/

相关文章:

c++ - 关于c++构造函数的问题

android - 如何在不调用 api 的情况下显示数据?

java - Android Firebase-未将所有键作为列表获取,我该怎么办?

android - CoordinatorLayout 状态栏填充在 fragment 事务期间消失

java - 仅在一个 Android Activity 中执行线程

android - 如何连接单独声明的修饰符?

javascript - 如何从构造函数中的函数返回对象属性?

android - 无法实例化 Activity java.lang.ClassNotFoundException

java - Prince 类型中的方法 Encrypt(long, long, long, long, int) 不适用于参数 (String, long, long, long, int)

java - Kotlin 中的私有(private)构造函数