175

What's the essential difference between these two methods? When I create a TextView, should I use one over the other for performance?

Edit: What's the difference from

onCreateView() {
  root = some view
  View v = new View(some context);
  root.add(v);
  return root;
}


onViewCreated() {
  View v = new View(some context);
  getView().add(v);
}
Smith
  • 1,839
  • 2
  • 12
  • 6
  • 1
    I added an edit to explain my confusion. If one method comes right after the other, why are there two? Can't all the view creation be done within a single method like as in above? – Smith Aug 04 '14 at 13:14
  • 11
    If you have to google and guess, there's probably badly named methods. – Balázs Németh Dec 11 '14 at 10:11

11 Answers11

137

We face some crashes initializing view in onCreateView.

You should inflate your layout in onCreateView but shouldn't initialize other views using findViewById in onCreateView.

Because sometimes view is not properly initialized. So always use findViewById in onViewCreated(when view is fully created) and it also passes the view as parameter.

onViewCreated is a make sure that view is fully created.

onViewCreated android Documentation

Called immediately after onCreateView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle) has returned, but before any saved state has been restored in to the view. This gives subclasses a chance to initialize themselves once they know their view hierarchy has been completely created. The fragment's view hierarchy is not however attached to its parent at this point.

Zar E Ahmer
  • 33,936
  • 20
  • 234
  • 300
  • 4
    Thanks. I also faced this problem and used component.`post`(...) method to wait till it is shown. Probably will make findViewById and other initialization in `onViewCreated`. – CoolMind Oct 04 '16 at 09:17
  • 33
    Where was that text quoted from? I couldn't find it in the official documentation. – Daniel Jun 01 '17 at 20:06
  • Can you please post the reference from Developer site of the statement quoted herewith? – Namrata Bagerwal Apr 03 '19 at 09:12
  • 12
    This isn't actually correct. You can find a view in onCreateView, but only after you've inflated it and only from the view you inflated already. Fragment.findViewById() is not safe, but View.findViewById() is safe if you already inflated the fragment view. – colintheshots Jul 26 '19 at 16:24
51

onViewCreated is called immediately after onCreateView (the method you initialize and create all your objects, including your TextView), so it's not a matter of performance.

From the developer site:

onViewCreated(View view, Bundle savedInstanceState)

Called immediately after onCreateView(LayoutInflater, ViewGroup, Bundle) has returned, but before any saved state has been restored in to the view. This gives subclasses a chance to initialize themselves once they know their view hierarchy has been completely created. The fragment's view hierarchy is not however attached to its parent at this point.

Source: Fragment#onViewCreated

Community
  • 1
  • 1
u3l
  • 3,342
  • 4
  • 34
  • 51
31

It's better to do any assignment of subviews to fields in onViewCreated. This is because the framework does an automatic null check for you to ensure that your Fragment's view hierarchy has been created and inflated (if using an XML layout file) properly.

Code snippet from: FragmentManger.java

// This calls onCreateView()
f.mView = f.performCreateView(f.getLayoutInflater(f.mSavedFragmentState), null, f.mSavedFragmentState);

// Null check avoids possible NPEs in onViewCreated
// It's also safe to call getView() during or after onViewCreated()
if (f.mView != null) {
    f.mView.setSaveFromParentEnabled(false);
    if (f.mHidden) f.mView.setVisibility(View.GONE);
    f.onViewCreated(f.mView, f.mSavedFragmentState);
}
orangemako
  • 944
  • 1
  • 11
  • 21
  • 6
    it also separates any initialization logic from the view hierarchy inflation/creation logic – orangemako Aug 06 '15 at 16:53
  • 1
    This is interesting, do you have any additional resources on why this approach is better? Does that mean every onCreateView method should only consist of a "return inflater.inflate(R.layout.layout_file, container, false);" and onviewcreated should have all "findViewById" methods? What performance boost does this create? Would it make transitions faster? – android_student Sep 18 '15 at 20:16
  • To answer your first question, `onCreateView` is used to create the fragment's view hierarchy. This can be via XML inflation or dynamic creation (i.e., creating Java views programatically). So you may not call `inflate` at all. But you should return some parent view if the fragment needs to have a UI element. Otherwise return `null`. – orangemako Sep 20 '15 at 01:15
  • There isn't a performance boost at all. Looking at the `FragmentManager` and fragment code for `performCreateView`, which calls `onCreateView` https://github.com/android/platform_frameworks_base/blob/3f453164ec884d26a556477027b430cb22a9b7e3/core/java/android/app/Fragment.java#L2047, you are guaranteed a few things tho for the `onViewCreated` lifecycle callback: – orangemako Sep 20 '15 at 01:23
  • 1. The view hierarchy will be attached to the container if the fragment has been dynamically added to its parent activity. 2. You can safely do view lookups without worrying about NPEs. 3. I'm not that familiar with animations, but the fragment transition will have already been started (i.e., sent over to the UI thread message queue). – orangemako Sep 20 '15 at 01:23
18

onCreateView() is the Fragment equivalent of onCreate() for Activities and runs during the View creation.
onViewCreated() runs after the View has been created.

should I use one over the other for performance? NO. There's no evidence of a performance boost.

There is actually an onCreate() method in Fragments too, but it's rarely used (I do never use it, nor find a good use case for it).

I always use onCreateView() in Fragments as a replacement for onCreate().
And I'm happy with that.

Ahmed Maad
  • 367
  • 5
  • 16
Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
  • 2
    @npace, why? I also think `onCreateView` is an equivalent of Activity's `onCreate`. – CoolMind Oct 04 '16 at 09:19
  • 2
    @CoolMind Well, nPace is not *totally* wrong, since there's an `onCreate()` method in Framents as well. But it's **never** used (or, at least, I do **never** use it). I always use `onCreateView()` in Fragments as a replacement. – Phantômaxx Oct 04 '16 at 09:22
  • 1
    @Rotwang, agree with you! Some tutorials use onCreate to put setHasOptionsMenu(true), but I think it would better do in onCreateView or onViewCreated. – CoolMind Oct 04 '16 at 09:34
  • 1
    @CoolMind I do totally agree. Maybe I used the wrong words in my answer. – Phantômaxx Oct 04 '16 at 09:36
  • 1
    @Rotwang, you said right. When I used fragments first time, I also didn't know why onCreate is not used. – CoolMind Oct 04 '16 at 09:40
  • 1
    Normally you want to use `onCreate` to do non-view-related things like store off arguments that were passed in. `onCreateView` should only contain logic directly related to the view. – ashishduh Oct 26 '16 at 16:03
  • I initialize data in onCreate() which I get using getArguments(). – Rahul Rastogi Mar 16 '17 at 05:34
  • 1
    You should use `onCreate()` and `onCreateView()` properly. `onCreate()` will only be called once on a fragment instance, while `onCreateView()` theoretically can be called many times (theoretically, Android can delete a fragment's view if a fragment is not shown on a screen (to save memory), and then when it's shown on the screen again it calls `onCreateView()` again to re-create the view. – Peppe L-G Oct 12 '19 at 07:23
17

The docs for Fragment.onCreateView() now says:

It is recommended to only inflate the layout in this method and move logic that operates on the returned View to onViewCreated(View, Bundle).

No need for us to understand why; we just need to do as the docs says, but it would be interesting to know why this recommendation exists. My best guess is separation of concern, but IMHO this makes it a little bit more complicated than it has to be.

Peppe L-G
  • 7,351
  • 2
  • 25
  • 50
  • If the reason is separation of concern, then why does Activity inflate its layout in `setContentView()` in `onCreate()`? – Minh Nghĩa Jun 21 '20 at 16:50
  • @MinhNghĩa Good point. The answer to that questions could simply be that it was designed by a different programmer thinking differently (fragments were introduced some years after we first got Android), but who knows. – Peppe L-G Jun 22 '20 at 07:33
14

onCreateView returns the inflated view. OnViewCreated is called just after onCreateView and get has parameter the inflated view. Its return type is void

Alexander Farber
  • 21,519
  • 75
  • 241
  • 416
Blackbelt
  • 156,034
  • 29
  • 297
  • 305
  • 1
    I added an edit to explain my confusion. If one method comes right after the other, why are there two? Can't all the view creation be done within a single method like as in above? – Smith Aug 04 '14 at 13:32
  • 3
    onCreateView should return quickly. OnViewCreate can be used to perform initialization stuff, for instance. As I said, onViewCreated has as parameter the View you inflated inside onCreateView. So you can avoid the `getView` call – Blackbelt Aug 04 '14 at 13:33
8
  • Ok, so If we are going to talk about onCreateView() and onViewCreated(). It is worth while to talk a little about the fragment lifecycle. The full documentation about the fragment lifecycle can be found HERE, I recommend that you read up on it, as we will only be talking about the states relevant to onCreateView() and onViewCreated().

  • The fragment lifecycle contains 5 states:

  • 1) INITIALIZED

  • 2) CREATED

  • 3) STARTED

  • 4) RESUMED

  • 5) DESTROYED

  • The reason that we need to talk about the fragment lifecycle is because both onCreateView() and onViewCreated() get called during the CREATED state in the lifecycle.

  • So when a fragment is instantiated, it begins in the INITIALIZED state, for example when you see:

CustomFragment frag1 = new CustomFragment() //`INITIALIZED` state
CustomFragment.class                        //`INITIALIZED` state

  • The .class syntax is the class literal syntax and for a brief summary I would recommend reading the blog post HERE

  • For a fragment to transition into other lifecycle states, it must be added to a Fragment Manager.

The Fragment Manager is responsible for determining what state its fragment should be in and then moving them into that state.

Difference between onCreateView() and onViewCreated()

  • Once the fragment has been added to the Fragment Manager, onAttach() is called to attach the fragment to the host activity.

  • Once onAttch() is called the fragment enters the CREATED state. It is in this state that the Android system begins creating the fragment's view. This can be done a few ways, for example the documentation states:

In most cases, you can use the fragment constructors that take a @LayoutId, which automatically inflates the view at the appropriate time. You can also override onCreateView() to programmatically inflate or create your fragment's view

  • If we look at the documentation for onCreateView() we see that:

It is recommended to only inflate the layout in this method and move logic that operates on the returned View to onViewCreated

Conclusion

  • Now combining everything we can come to the conclusion, both onCreateView() and onViewCreated() are called during the CREATED state of a fragment's life cycle. However, onCreateView() is called first and should only be used to inflate the fragment's view. onViewCreated() is called second and all logic pertaining to operations on the inflated view should be in this method.
Tristan Elliott
  • 594
  • 10
  • 8
3

In the Google Documentation

There is a new solution to declare the xml resource in the Fragment superclass

class ExampleFragment : Fragment(R.layout.example_fragment) { }

Then bind the view in onViewCreate

private lateinit var binding : ExampleFragmentBinding

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    binding = ExampleFragmentBinding.bind(view)
}

In this way you do not need to inflate view in onCreatedView or handle the view in onDestroy

Emmanuel Conradie
  • 345
  • 1
  • 5
  • 20
2

The main reason I would use onViewCreated is since it separates any initialization logic from the view hierarchy inflation/creation logic which should go in the onCreateView . All other performance characteristics look the same.

Astha Garg
  • 1,022
  • 7
  • 21
AmeyaB
  • 989
  • 8
  • 12
2

i think the main different between these is when you use kotlin.in onCreateView() every Time you want to access to view in your xml file you should use findViewById but in onViewCreated you can simply access to your view just by calling the id of it.

  • Is this really true? I'm getting null for the view if I just use the id in the code either way. I need to always use the findViewById. – Jim Leask Jul 19 '18 at 16:52
  • 1
    No it's not.. oncreate view instantiates the view, onviewcreated is called after oncreateview and before saved states are restored... it's more a timing issue in the lifecycle of the fragment – me_ Oct 23 '18 at 05:57
1

onCreateView is used in fragment to create layout and inflate view. onViewCreated is used to reference the view created by above method. Lastly it is a good practice to define action listener in onActivityCreated.