I have seen two general practices to instantiate a new Fragment in an application:

Fragment newFragment = new MyFragment();

and

Fragment newFragment = MyFragment.newInstance();

The second option makes use of a static method newInstance() and generally contains the following method.

public static Fragment newInstance() 
{
    MyFragment myFragment = new MyFragment();
    return myFragment;
}

At first, I thought the main benefit was the fact that I could overload the newInstance() method to give flexibility when creating new instances of a Fragment - but I could also do this by creating an overloaded constructor for the Fragment.

Did I miss something?

What are the benefits of one approach over the other? Or is it just good practice?

upvote
  flag
When there are parameters, there is no choice, and this is extensively answered here. Still, the question remains for no-argument construction of the fragment. – rds
upvote
  flag
After learning about factory pattern's and how a calling class not instantiating an object itself helps in decoupling them, I thought this would be a strong point for the newInstance() method. Am I wrong on this? I haven't seen this specific argument spoken of as a benefit. – Mobile Applications

11 Answers 11

up vote 887 down vote accepted

If Android decides to recreate your Fragment later, it's going to call the no-argument constructor of your fragment. So overloading the constructor is not a solution.

With that being said, the way to pass stuff to your Fragment so that they are available after a Fragment is recreated by Android is to pass a bundle to the setArguments method.

So, for example, if we wanted to pass an integer to the fragment we would use something like:

public static MyFragment newInstance(int someInt) {
    MyFragment myFragment = new MyFragment();

    Bundle args = new Bundle();
    args.putInt("someInt", someInt);
    myFragment.setArguments(args);

    return myFragment;
}

And later in the Fragment onCreate() you can access that integer by using:

getArguments().getInt("someInt", 0);

This Bundle will be available even if the Fragment is somehow recreated by Android.

Also note: setArguments can only be called before the Fragment is attached to the Activity.

This approach is also documented in the android developer reference: https://developer.android.com/reference/android/app/Fragment.html

1 upvote
  flag
Then they should have make newInstance() for us to override – urSus
6 upvote
  flag
@Vlasto unfortunately static methods can't be overridden. – AJD
7 upvote
  flag
@yydl I think I'm missing something here, couldn't you use a constructor here anyway, one that creates the Bundle and calls setArguments() still since it will only be called by your code (and not when Android re-creates your fragment)? – Mike Tunnicliffe
1 upvote
  flag
Ah, I see that lint gives a warning if you a non-default constructor. – Mike Tunnicliffe
5 upvote
  flag
This is also documented fairly well in the frag docs: developer.android.com/reference/android/app/… – greg7gkb
1 upvote
  flag
Is there an advantage to using a Bundle here? Isn't it easier to just set the int value of myFragment straight away? e.g. myFragment.someInt = someInt; return myFragment; – mgibson
9 upvote
  flag
@mgibson You must use a bundle if you want the data to be available when the fragment is later recreated. – yydl
1 upvote
  flag
@yydl and what if you want to pass objects? should this be done using a thread instead? I've successfully passed objects from my main activity into 3 different fragments by accesors, but I'm afraid that at some point I'll get a null pointer even though the main activity is the parent activity. – Ben Sewards
2 upvote
  flag
@BenSewards Actually, the best way to do that would probably be to implement Parcelable and then putParcelable on the Bundle (you can also use Serializable, but it's not recommended) – yydl
upvote
  flag
@yydl thanks I'll definitely look into it – Ben Sewards
73 upvote
  flag
Being FORCED to create a no-argument constructor for fragments is potentially the single biggest gotcha in all of programming, anywhere. It forces a complete paradigm shift in object creation and initialization. If you're new to Android and have stumbled on this thread, please read the answer above over and over and over again. – rmirabelle
upvote
  flag
It is possible to preserve the fragment and its data such as those passed to constructors by calling setRetainInstance(true). This method makes sure the fragment won't call onCreate and onDestroy at config change like orientation. //allinonescript.com/questions/11182180/… – inmyth
3 upvote
  flag
@yydl great answer and i totally get the solution. You said "If Android decides to recreate your Fragment later". Could you give some examples or point to the documentation where Android does decide to do this? – Kaushik Gopal
upvote
  flag
+1 for great answer this method also works for dynamically added fragments using fragmentmanager.add() – Illegal Argument
upvote
  flag
@rmirabelle that's how a(ny) framework works, it give constraints on classes/objects it can work with. Activity.onCreate instead of a constructor is similar not to mention afterPropertiesSet in Spring. You can try to implement a type-safe method of instantiating a class with an arbitrary constructor in Java, I don't think it's possible. – TWiStErRob
5 upvote
  flag
I would argue with that assertion. First, type-safeness is a language concern, not a framework concern. Secondly, IMO, the framework is stepping into the area of "things your API must never do". If I want to pass the library of congress into my fragment constructor, then I should be allowed to. The "no-args" constructor contract basically kills the use of dependency injection in fragments - major yuck. – rmirabelle
3 upvote
  flag
@fd I totally agree that a non-default constructor that initializes a Bundle and use setArguments() would do the trick too. You're not gonna use any parameter here anyway, but in onCreateView, so when the system creates the fragment with the default constructor (which you have to declare), it's not a problem. Why a static factory method, then ? – Joffrey
upvote
  flag
@Joffrey Using setArguments is only half of the battle. You also need to access the stuff using getArguments. – yydl
1 upvote
  flag
@yydl Well in any case, you have to use getArguments, because this is how the system works. The fact that you use a static factory method or an overloaded constructor to make your setArguments call does not affect the constraints you have to access the data. Using an overloaded constructor won't change anything here. – Joffrey
upvote
  flag
@yydl On the other hand, you could as well use setters to set some attributes of your fragment even when you use a static factory method. It would be as bad as doing so from an overloaded constructor. Using a sfm does not force programmers to call setArguments, you can do as much bad stuff as with a constructor. – Joffrey
1 upvote
  flag
@Joffrey True. I meant to say that by forcing this strange pattern, Android is highlighting that things are strange here. Essentially driving people to this question & answer. – yydl
upvote
  flag
@yydl That's right. Both approaches work, but I guess using the one recommended by Google is probably better, at least when your code is read by other programmers. – Joffrey
1 upvote
  flag
@Joffrey what I don't still don't understand is what the advantage of using a static method is. Why can't I just use the default constructor and then create and send the bundle directly from my code instead of calling a static method that does exactly the same thing? OTOH, using a static method for creating the fragment is a major problem when you need to create general code which is then overriden, since you can't overload a static method. If the whole idea is to force the "sender" to send the correct parameters you can define an object that contains the parameters that fragment needs. – theblitz
upvote
  flag
upvote
  flag
I am trying to do this for an abstract Fragment class, and I get an error that in the BaseListFragment myFragment = new BaseListFragment(); line -- saying that I cannot instantiate an object of an abstract class. What's the way out? – dowjones123
1 upvote
  flag
@anticafe You can actually use getArguments().getInt anywhere in the fragment... – yydl
upvote
  flag
where is fragment's onCreate() by the way? – NarendraJi
upvote
  flag
When would one justify using android:configChanges="orientation|keyboardHidden|screenSize‌​" ? – Luke Allison
1 upvote
  flag
With android studio, if you use the assisted fragment creation procedure (File>new>fragment) you will have a fragment with this approach already implemented – Apperside
upvote
  flag
Also you can use the Model View Presenter pattern, so the data in memory could be persisted anyway even if the fragment or activity is restarted. Here are a basic explanation about this. github.com/konmik/konmik.github.io/wiki/… – westrada
upvote
  flag
With this approach wouldn't you have to break down any object into a primitive? I want to pass a Date object to the fragment class, but there's no way to do that. Is the only solution breaking down the Date into day, month, and year ints? If so that seems insane that I have to destruct the object then reconstruct it inside the fragment. – Casey Hancock
1 upvote
  flag
@CaseyHancock See my comment above directed towards "@BenSewards" on July 30, 2013. Basically you can pass any object that can be placed into the bundle by using Parcelable (and Serializable). For a Date object, it looks like it only implements Serializable, but see here. – yydl

The only benefit in using the newInstance() that I see are the following:

  1. You will have a single place where all the arguments used by the fragment could be bundled up and you don't have to write the code below everytime you instantiate a fragment.

    Bundle args = new Bundle();
    args.putInt("someInt", someInt);
    args.putString("someString", someString);
    // Put any other arguments
    myFragment.setArguments(args);
    
  2. Its a good way to tell other classes what arguments it expects to work faithfully(though you should be able to handle cases if no arguments are bundled in the fragment instance).

So, my take is that using a static newInstance() to instantiate a fragment is a good practice.

1 upvote
  flag
1) How is this any different than putting the logic in a constructor? Both are single places where you include this logic. 2) How are parameters on a static factory any different than parameters on a constructor? Both tell what arguments are expected. My point being it's a different paradigm, sure, but there's no clear benefit to this over using constructors. – RJ Cuthbertson
upvote
  flag
You cannot use custom constructors for fragment. Framework uses the no argument constructor for restoring fragments. – 500865
3 upvote
  flag
Yes, I agree with you there. I'm saying conceptually there is no benefit in using the static factory pattern instead of using overloaded constructors, and vice versa. Both of your points are valid in both patterns; there is no benefit of using one over the other. Android forces you to use the static factory pattern - but there is no benefit to using one or the other. – RJ Cuthbertson
upvote
  flag
pastebin.com/EYJzES0j – RJ Cuthbertson
upvote
  flag
@RJCuthbertson A possible benefit would be the ability to create and return subclasses of the static factory method's class i.e. to return an appropriate subclass for the situation. – urgentx

There is also another way:

Fragment.instantiate(context, MyFragment.class.getName(), myBundle)
upvote
  flag
If I am not mistaken, this is only possible when you use the Android Support library. – Timo
upvote
  flag
Its also possible without support library. – user1145201
2 upvote
  flag
Tried this with the support library, but in onCreateView (in my fragment), the bundle passed was null, so I went with the setArguments/getArguments option and it worked (for anyone reading this). – Jrop
1 upvote
  flag
Interesting, I have not seen this approach before. Does it have any advantages over other approaches to instantiating a Fragment? – Igor Ganapolsky
15 upvote
  flag
From the developer docs, instantiate() Creates a new instance of a Fragment with the given class name. This is the same as calling its empty constructor. – anon
1 upvote
  flag
Although they mentioned same as calling empty constructor. "args.setClassLoader(f.getClass().getClassLoader());" is called underneath for Bundle arguments – Gökhan Barış Aker
upvote
  flag
@IgorGanapolsky my guess would be that it is the method they use when fragment is in xml: <fragment android:name="..."> – TWiStErRob
upvote
  flag
@IgorGanapolsky or it has the same use case as Intent.setClassName, i.e. not having a class reference because it's in another (android) package? – TWiStErRob

I disagree with yydi answer saying:

If Android decides to recreate your Fragment later, it's going to call the no-argument constructor of your fragment. So overloading the constructor is not a solution.

I think it is a solution and a good one, this is exactly the reason it been developed by Java core language.

Its true that Android system can destroy and recreate your Fragment. So you can do this:

public MyFragment() {
//  An empty constructor for Android System to use, otherwise exception may occur.
}

public MyFragment(int someInt) {
    Bundle args = new Bundle();
    args.putInt("someInt", someInt);
    setArguments(args);
}

It will allow you to pull someInt from getArguments() latter on, even if the Fragment been recreated by the system. This is more elegant solution than static constructor.

For my opinion static constructors are useless and should not be used. Also they will limit you if in the future you would like to extend this Fragment and add more functionality to the constructor. With static constructor you can't do this.

Update:

Android added inspection that flag all non-default constructors with an error.
I recommend to disable it, for the reasons mentioned above.

4 upvote
  flag
Another benefit of having a static method, which I did not mention above is that you cannot accidentally set properties from it. – yydl
4 upvote
  flag
Additionally, with regards to your point about "extend this fragment", this method would actually be really bad if you ever extend the class. Calling super will cause the setArguments() call to only be effective for either the child or parent, but not both! – yydl
2 upvote
  flag
@yydl why not both? – Ilya_Gazman
upvote
  flag
Well it would depend on when you call super(...) in the child's implementation, but basically the point is the setArguments() only works for the last bundle that's set. – yydl
2 upvote
  flag
@yydle you can avoid this situation by calling get arguments to initialize the child Bundle. Java way always better. – Ilya_Gazman
5 upvote
  flag
True, but that's another reason to encourage people to use the pattern Google has suggested. Of course, we all agree that your solution is 100% technically feasible. Much the same way there are many ways to do lots of things. The question, though, is whether it's the best. And I strongly feel that using the constructor does not represent the true nature of how this is supposed to work. – yydl
3 upvote
  flag
I agree with @yydl that static creation is better. One other benefit is dependency injection of future new dependencies - constructor is ill fitted for that and will likely cause more code change (or more constructors to be added). – Boon
1 upvote
  flag
Android Studio now throws an error for all non-default constructors in fragments, so this no longer works. – Sheharyar
upvote
  flag
@Sheharyar I added it to the answer, I recommend you to disable this inspection. – Ilya_Gazman
upvote
  flag
When the Fragment is recreated, the non-default constructor is called, right? So how does this help? You quoted it yourself So overloading the constructor is not a solution – cricket_007
1 upvote
  flag
@cricket_007 I quoted it because I disagree with it, and here I offer the native Java approach to this issue – Ilya_Gazman
upvote
  flag
I think I understand that, but public MyFragment(int someInt) won't be called by the OS, so... yeah – cricket_007
1 upvote
  flag
@cricket_007 It sound like you don't understand the setArguments method. When you call it is saves the data locally, so when the system will recreate the fragment from default contractor you will have the arguments as you set them in the non default constructor. – Ilya_Gazman
1 upvote
  flag
No, I understand that piece. I think I see what you are getting at now -- You can supplement the default constructor with an overloaded one and the static one is useless. – cricket_007
upvote
  flag
@cricket_007 yep, this is it – Ilya_Gazman
upvote
  flag
Some people simply forget to implement the no-arg one, though so that is why the static solution exists. Both are "native Java approaches" – cricket_007
upvote
  flag
Static solution supose to be a construcor but you can't override it. So its anty-oop aproach – Ilya_Gazman

I believe I have a much simpeler solution for this.

public class MyFragment extends Fragment{

   private String mTitle;
   private List<MyObject> mObjects;

   public static MyFragment newInstance(String title, List<MyObject> objects)
   MyFragment myFrag = new MyFragment();
   myFrag.mTitle = title;
   myFrag.mObjects = objects;
   return myFrag;
   }
8 upvote
  flag
mObjects will be cleared if MyFragment happens to be recreated (the user goes to the device home screen and later opens up the app which left off at MyFragment). You can retain mObjects by sending MyFragment a bundle as arguments. – ynnadkrap
upvote
  flag
Also, how is the static method accessing non-static member variables? – OrhanC1
2 upvote
  flag
@ynnadkrap You are correct, using a bundle is the way to go here. – Stefan Bogaard
1 upvote
  flag
@OrhanC1 According to this example code, static method is not accessing to the member variables. The instance of MyFragment is accessing to its members. There is no error here. However, I do not recommend this answer to anyone because when your fragment is removed from the memory to open up some space by the android os then after restarting the activity and this fragment will be created with default empty constructor without assigning ant variables. – Gunhan
upvote
  flag
@Gunhan You're right! It's not. Sorry for the confusion :) – OrhanC1

Since the questions about best practice, I would add, that very often good idea to use hybrid approach for creating fragment when working with some REST web services

We can't pass complex objects, for example some User model, for case of displaying user fragment

But what we can do, is to check in onCreate that user!=null and if not - then bring him from data layer, otherwise - use existing.

This way we gain both ability to recreate by userId in case of fragment recreation by Android and snappiness for user actions, as well as ability to create fragments by holding to object itself or only it's id

Something likes this:

public class UserFragment extends Fragment {
    public final static String USER_ID="user_id";
    private User user;
    private long userId;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        userId = getArguments().getLong(USER_ID);
        if(user==null){
            //
            // Recreating here user from user id(i.e requesting from your data model,
            // which could be services, direct request to rest, or data layer sitting
            // on application model
            //
             user = bringUser();
        }
    }

    public static UserFragment newInstance(User user, long user_id){
        UserFragment userFragment = new UserFragment();
        Bundle args = new Bundle();
        args.putLong(USER_ID,user_id);
        if(user!=null){
            userFragment.user=user;
        }
        userFragment.setArguments(args);
        return userFragment;

    }

    public static UserFragment newInstance(long user_id){
        return newInstance(null,user_id);
    }

    public static UserFragment newInstance(User user){
        return newInstance(user,user.id);
    }
}
2 upvote
  flag
You said: "We can't pass complex objects, for example some User model, " - It is not true, we can. Like this: User user = /*...*/ put the user to the bundle: Bundle bundle = new Bundle(); bundle.putParcelable("some_user", user); and get the user from arguments: User user = getArguments().getParcelable("some_user"); The object must be implement Parcelable interface. link – Adam Varhegyi
3 upvote
  flag
Well, yes, but when class is complex and contains referrers to another objects... I personally prefer to keep it simple, either I have object, or I don't and then need to get it – Tigra

While @yydl gives a compelling reason on why the newInstance method is better:

If Android decides to recreate your Fragment later, it's going to call the no-argument constructor of your fragment. So overloading the constructor is not a solution.

it's still quite possible to use a constructor. To see why this is, first we need to see why the above workaround is used by Android.

Before a fragment can be used, an instance is needed. Android calls YourFragment() (the no arguments constructor) to construct an instance of the fragment. Here any overloaded constructor that you write will be ignored, as Android can't know which one to use.

In the lifetime of an Activity the fragment gets created as above and destroyed multiple times by Android. This means that if you put data in the fragment object itself, it will be lost once the fragment is destroyed.

To workaround, android asks that you store data using a Bundle (calling setArguments()), which can then be accessed from YourFragment. Argument bundles are protected by Android, and hence are guaranteed to be persistent.

One way to set this bundle is by using a static newInstance method:

public static YourFragment newInstance (int data) {
    YourFragment yf = new YourFragment()
    /* See this code gets executed immediately on your object construction */
    Bundle args = new Bundle();
    args.putInt("data", data);
    yf.setArguments(args);
    return yf;
}

However, a constructor:

public YourFragment(int data) {
    Bundle args = new Bundle();
    args.putInt("data", data);
    setArguments(args);
}

can do exactly the same thing as the newInstance method.

Naturally, this would fail, and is one of the reasons Android wants you to use the newInstance method:

public YourFragment(int data) {
    this.data = data; // Don't do this
}

As further explaination, here's Android's Fragment Class:

/**
     * Supply the construction arguments for this fragment.  This can only
     * be called before the fragment has been attached to its activity; that
     * is, you should call it immediately after constructing the fragment.  The
     * arguments supplied here will be retained across fragment destroy and
     * creation.
     */
    public void setArguments(Bundle args) {
        if (mIndex >= 0) {
            throw new IllegalStateException("Fragment already active");
        }
        mArguments = args;
    }

Note that Android asks that the arguments be set only at construction, and guarantees that these will be retained.

EDIT: As pointed out in the comments by @JHH, if you are providing a custom constructor that requires some arguments, then Java won't provide your fragment with a no arg default constructor. So this would require you to define a no arg constructor, which is code that you could avoid with the newInstance factory method.

EDIT: Android doesn't allow using an overloaded constructor for fragments anymore. You must use the newInstance method.

upvote
  flag
When would one justify using android:configChanges="orientation|keyboardHidden|screenSize‌​" ? – Luke Allison
upvote
  flag
Android Studio now throws an error for all non-default constructors in fragments, so this no longer works. – Sheharyar
4 upvote
  flag
Holy man, I wonder how many droid developers have ever written code outside of droid. This is insane that we cannot use the approach you describe. There are NO compelling arguments from any comment as to why we HAVE to use static factory method. It's even more disturbing that they would raise an error when compiling. This is definitely the best answer provided and shows that there is no benefit to sfm. – MPavlak
1 upvote
  flag
Well, there is one subtle reason. You are free to create your own constructor with arguments, but there still needs to be a no-arg constructor as well. Since classes always have an implicit no-arg constructor unless a constructor with args is explicitly defined, this means that you would have to define both your arg-constructor and a no-arg constructor explicitly, or the system would not be able to invoke any no-arg constructor. I believe this is why the recommendation is to instead use a static factory method - it simply reduces the risk of forgetting to define a no-arg constructor. – JHH
upvote
  flag
@JHH that will fail at compile time itself, so not that big of a risk. However, the issue here is that constructor overloading, a key programming paradigm, is being denied by Android. – prakharsingh95
upvote
  flag
It will not fail at compile time. Android lint will complain about the lack of a default constructor but it will not prevent a debug build. In the event of a recreated fragment it will cause a runtime exception. – JHH
upvote
  flag
@JHH I don't know the details of how Android constructs the fragments. I meant to emphasise that since it would still result in a runtime exception, it can easily be corrected. However, if you store data outside of the argument bundle, it would be a hard bug to track down. But yes, the requirement of a default constructor is a pretty good reason as well. – prakharsingh95
upvote
  flag
The fact that fragments are only recreated in somewhat rare cases such as in a low memory situation or due to a configuration change makes it quite easy to forget adding a default constructor. That's why they added the lint warning I guess. Normally you create the fragment yourself with arguments, possibly not using the default constructor, and the default constructor is only used by the system in exceptional cases. If you use the static factory method, you are essentially using the same code as the system will, I.e., no-arg constructor followed by setArguments. – JHH

Best way to instantiate the fragment is use default Fragment.instantiate method or create factory method to instantiate the the fragment
Caution: always create one empty constructor in fragment other while restoring fragment memory will throw run-time exception.

Best practice to instance fragments with arguments in android is to have static factory method in your fragment.

public static MyFragment newInstance(String name, int age) {
    Bundle bundle = new Bundle();
    bundle.putString("name", name);
    bundle.putInt("age", age);

    MyFragment fragment = new MyFragment();
    fragment.setArguments(bundle);

    return fragment;
}

You should avoid setting your fields with the instance of a fragment. Because whenever android system recreate your fragment, if it feels that the system needs more memory, than it will recreate your fragment by using constructor with no arguments.

You can find more info about best practice to instantiate fragments with arguments here.

setArguments() is useless. It only brings a mess.

public class MyFragment extends Fragment {

    public String mTitle;
    public String mInitialTitle;

    public static MyFragment newInstance(String param1) {
        MyFragment f = new MyFragment();
        f.mInitialTitle = param1;
        f.mTitle = param1;
        return f;
    }

    @Override
    public void onSaveInstanceState(Bundle state) {
        state.putString("mInitialTitle", mInitialTitle);
        state.putString("mTitle", mTitle);
        super.onSaveInstanceState(state);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle state) {
        if (state != null) {
            mInitialTitle = state.getString("mInitialTitle");
            mTitle = state.getString("mTitle");
        } 
        ...
    }
}
upvote
  flag
Except you have just been forced to override one more method and make a field that could have been isolated to the onViewCreated scope. It's convenience I guess, many ways to do the same thing. Also it's an easy way to check for updates done by the user (compare the bundles of getArguments and the bundle from onSaveInstanceState) – Sumido
upvote
  flag
@Asagen, I like your comment about compare initial and user values. I edited code and consider that it is still uniform and clear witout getArguments stuff. What about onViewCreated scope... We can restore state bundle there. But I just prefer make onCreateView light and fast and do all heavy initialization inside a onActivityCreated because Fragment.getActivity() sometimes like to return null and because of onAttach() changes in new version of API 23. – Vadim Star
upvote
  flag
All you did here was move set and get Arguments into saveInstanceState. You're essentially doing the same thing that is done "under the hood" – cricket_007
upvote
  flag
@cricket_007, or just opposite. Using saveInstanceState is "under the hood". And using of Arguments is duplication of functionality that make you double check: first Arguments values and then saveInstanceState values. Because you have to use saveInstanceState any way. What about Arguments... they are not necessary. – Vadim Star
upvote
  flag
Arguments are the equivalent of Intent extras for fragments. They are not useless, they contain the initial parameters which is different from the current state. – BladeCoder

Some kotlin code:

companion object {
    fun newInstance(first: String, second: String) : SampleFragment {
        return SampleFragment().apply {
            arguments = Bundle().apply {
                putString("firstString", first)
                putString("secondString", second)
            }
        }
    }
}

And you can get arguments with this:

val first: String by lazy { arguments.getString("firstString") }
val second: String by lazy { arguments.getString("secondString") }

Not the answer you're looking for? Browse other questions tagged or ask your own question.