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