Wednesday, July 31, 2013

What is the difference between new MyFragment() and MyFragment.newInstance()? Should I prefer one over the other?

Using "newInstance()" to Instantiate a Fragment


I recently came across an interesting question on StackOverflow regarding Fragment instantiation:

What is the difference between new MyFragment() and MyFragment.newInstance()? Should I prefer one over the other?

Good question. The answer, as the title of this blog suggests, is a matter of proper design.
Here, the newInstance() method is what we call a "static factory method", a simple pattern that is often used as a way to instantiate an object without directly calling the object's default constructor. For example, it is often used to implement a Singleton design pattern:

public static class Singleton {
 
    private static final Singleton instance = null;
     
    /**
     * Make the class private to prevent direct instantiation. This
     * forces clients to call newInstance(), which will ensure the
     * class' Singleton property.
     */
    private Singleton() { }
    
    /**
     * If instance is null, then instantiate the object by calling
     * the default constructor (this is OK since we are calling
     * it from within the class). This method should be marked
     * "synchronized" if you plan on calling it from multiple threads!
     */
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

The programmer forces the client to call newInstance() to retrieve an instance of the class. This is important because simply providing a default constructor would allow the client access to multiple instances of the class (as this goes against the Singleton property).
The same general idea is often applied to fragments. Providing a static factory method for your fragments is good practice when you want to add initialization arguments to the newly instantiated object. For example, consider the following code:


public class MyFragment extends Fragment {
 
  /**
   * Static factory method that takes an int parameter,
   * initializes the fragment's arguments, and returns the
   * new fragment to the client.
   */
  public static MyFragment newInstance(int index) {
    MyFragment f = new MyFragment();
    Bundle args = new Bundle();
    args.putInt("index", index);
    f.setArguments(args);
    return f;
  }
}

Rather than having the client call the default constructor and manually set the fragment's arguments themselves, we provide a static factory method that does this for them. This is preferred over the default constructor for two reasons. One, it's convenient for the client, and two, it enforces well-defined behavior. By providing a static factory method, we protect ourselves from bugs down the line--we no longer need to worry about accidentally forgetting to initialize the fragment's arguments or incorrectly doing so.
Overall, while the difference between the two is mostly just a matter of design, this difference is really important because it provides another level of abstraction and makes code a lot easier to understand.
Leave a comment if this helped... it'll motivate me to write more of these blog posts in the future! :)

No comments:

Post a Comment