创建片段:构造函数与newInstance()

时间:2013-02-01 20:50:07

标签: android constructor android-fragments default-constructor

我最近厌倦了在创建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需要重新创建片段(方向更改或低内存)时,它会调用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不会抱怨它。 基本上我的问题是,为什么Google不希望您使用带Fragments参数的构造函数?

我唯一的猜测是,你不要尝试在不使用Bundle的情况下设置实例变量,Fragment在重新创建static newInstance()时不会被设置。通过使用public ImageRotatorFragment(int imageResourceId) { Log.v(TAG, "ImageRotatorFragment(int imageResourceId)"); mImageResourceId = imageResourceId; } 方法,编译器将不允许您访问实例变量。

{{1}}

我仍然觉得这不足以让我们不允许在构造函数中使用参数。其他人对此有所了解吗?

2 个答案:

答案 0 :(得分:59)

  

我个人发现使用构造函数比使用newInstance()和传递参数更常见。

factory method pattern在现代软件开发中经常使用。

  

所以基本上我的问题是,为什么Google不希望你使用带有Fragments参数的构造函数?

你回答了自己的问题:

  

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

正确。

  

我仍然觉得这不足以让我们不允许在构造函数中使用参数。

欢迎您的意见。欢迎您以每个构造函数或每个工作区的方式禁用此Lint检查。

答案 1 :(得分:0)

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