title: Creating a Fragment: constructor vs newInstance()
body: <p>I recently grew tired of constantly having to know <code>String</code> keys to pass arguments into <code>Bundles</code> when creating my <code>Fragments</code>. So I decided to make constructors for my <code>Fragments</code> that would take the parameters I wanted to set, and put those variables into the <code>Bundles</code> with the correct <code>String</code> keys, therefore eliminating the need for other <code>Fragments</code> and <code>Activities</code> needing to know those keys.</p>
  
  <pre><code>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);
  }
  </code></pre>
  
  <p>And then I pull out those arguments like normal.</p>
  
  <pre><code>@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];
      }
  }
  </code></pre>
  
  <p>However, Lint took issue with this, saying not to have subclasses of <code>Fragment</code> with constructors with other parameters, requiring me to use <code>@SuppressLint("ValidFragment")</code> to even run the app. The thing is, this code works perfectly fine. I can use <code>ImageRotatorFragment(int imageResourceId)</code> or the old school method <code>ImageRotatorFragment()</code> and call <code>setArguments()</code> manually on it. When Android needs to recreate the Fragment (orientation change or low memory), it calls the <code>ImageRotatorFragment()</code> constructor and then passes the same argument <code>Bundle</code> with my values, which get set correctly.</p>
  
  <p>So I have been searching for the "suggested" approach and see a lot of examples using <code>newInstance()</code> to create <code>Fragments</code> with parameters, which seems to do the same thing my constructor is. So I made my own to test it, and it works just as flawlessly as before, minus Lint whining about it.</p>
  
  <pre><code>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;
  }
  </code></pre>
  
  <p>I personally find that using constructors is a much more common practice than knowing to use <code>newInstance()</code> and passing parameters. I believe you can use this same constructor technique with Activities and Lint will not complain about it. <strong>So basically my question is, why does Google not want you to use constructors with parameters for <code>Fragments</code>?</strong></p>
  
  <p>My only guess is so you don't try to set an instance variable without using the <code>Bundle</code>, which won't get set when the <code>Fragment</code> gets recreated. By using a <code>static newInstance()</code> method, the compiler won't let you access an instance variable. </p>
  
  <pre><code>public ImageRotatorFragment(int imageResourceId) {
      Log.v(TAG, "ImageRotatorFragment(int imageResourceId)");
  
      mImageResourceId = imageResourceId;
  }
  </code></pre>
  
  <p>I still don't feel like this is enough reason to disallow the use of parameters in constructors. Anyone else have insight into this?</p>