Why use newInstance for DialogFragment instead of the constructor?

柔情痞子 提交于 2019-11-30 08:47:59

If you overload the constructor with MyAlertDialogFragment(int title), the Android system may still call the default MyAlertDialogFragment() constructor if the Fragment needs to be recreated and the parameter is then not passed.

If you create a DialogFragment that receives objects through the constructor, you will have problems when android recreates your fragment. This is what will happen:

  1. your code creates the dialog calling the constructor you have created and passing some arguments as dependencies.
  2. your dialog runs, and uses the dependencies that you passed though the constructor
  3. the user closes the app
  4. time passes, and android kills the fragment to free memory
  5. the user opens the app again
  6. android will recreate your dialog, this time using the default constructor. No arguments will be passed!
  7. Your dialog will be in a undesired state. It may try to use instance variables that you expected to pass through the constructor, but as they are not there you'll get a null pointer exception.

To avoid this, you need not to rely on the constructor to establish the dependencies, but in in Bundles (arguments and saved instances). That may force you to implement Parcelable in some classes, which sucks.

EDIT: you can reproduce Android killing the app (step 4) by enabling the "don't maintain Activities" in the Development settings. That's the way to easily test it.

Android relies on Fragments having a public, zero-argument constructor so that it can recreate it at various times (e.g. configuration changes, restoring the app state after being previously killed by Android, etc.).

If you do not have such a constructor (e.g. the one in the question), you will see this error when it tries to instantiate one:

Fragment$InstantiationException: Unable to instantiate fragment 
make sure class name exists, is public, and has an empty constructor that is public

Arguments given to it by Fragment.setArguments(Bundle) will be saved for you and given to any new instances that are (re)created. Using a static method to create the Fragment simply provides an easy way to setup the required arguments whilst maintaining a zero-argument constructor.

Srokowski Maciej

Because when android is recreating a fragment, it always uses the empty constructor, and by using newInstance() you can set data that fragment uses when recreating, for example when the screen is rotated

for example:

   public static FragmentExample newInstance(Parcelable uri) {
    FragmentExample fragmentExample = new FragmentExample();

    Bundle bundle = new Bundle();
    bundle.putParcelable("Uri", uri);
    fragmentExample.setArguments(bundle);

    return fragmentExample;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!