Member variables vs setArguments in Fragments

android, android-fragments, coding-style, java

Solution

I've also stumbled upon this and found a few advantages to using the arguments `Bundle` over instance fields:

If it's in a `Bundle` the Android system knows about it and can create and destroy your `Fragment` (using the mandatory parameterless/default constructor and usual lifecycle methods), and just pass in the arguments bundle again. This way no arguments get lost on a low memory killing spree or the eventual orientation changes (this often hits me on first deploy to a real device after development in the less-rotating emulator).

You can just pass the extras `Bundle` of an `Activity` as-is to a `Fragment` embedded in the layout; e.g. I often use this when I have an `Activity` that displays a `Fragment` "fullscreen" and needs some ID (or `ContentProvider` URI) to know what to display/do. I sometimes even add more stuff to a `Bundle` (or a copy) before I pass it on, e.g.

@Override
protected void onCreate(final Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);

  if (savedInstanceState == null) { // not a re-creation
    final Bundle args = new Bundle(getIntent().getExtras());
    args.putInt(CoverImageFragment.BACKGROUND_RESOURCE, android.R.color.black);
    final Fragment fragment = CoverImageFragment.newInstance(args);
    getSupportFragmentManager()
      .beginTransaction()
      .add(android.R.id.content, fragment)
      .commit();
  }
}

It keeps the way of developing a `Fragment` close to that of an `Activity`, i.e. `Bundle` as "input parameters, no exceptions".

As for the downsides you mentioned:

I think the overhead is minimal because you most likely won't be querying the `Bundle` in a tight loop, so getting your argument data out once in `onCreate()`, `onViewCreate()`, etc. isn't that bad.

For type-safety, `Bundle` has all the different `getXXXX()` methods, and even overloads to provide a default value if a something is missing/optional :)

As for the `newInstance()` methods, I think of them as an easy way to encapsulate the `new` and `setArguments()` calls for my `Fragment`; I sometimes provide an additional `MyFragment newInstance(String singleIdOfWhatToDisplay)` that creates both the `Bundle` and `Fragment` in one go and returns a ready-to-go `Fragment` instance.

Problem

I've noticed that in the Android reference for Fragments (notably DialogFragment) that they do a couple of things different from what I'd expect: 1). Use `public static foo newInstance()` method rather than a constructor. 2). Pass values to onCreateDialog using setArguments rather than member variables. I've read that newInstance appears to be preferrable when using reflection. However I really don't understand why they're passing parameters via a bundle. I'd have though using member variables would be safer (not using a string to fetch from a map) and would have less of an overhead. Any thoughts?

Original source