Home > Mobile >  Should I inflate the layout in onCreateView or onViewCreated?
Should I inflate the layout in onCreateView or onViewCreated?

Time:01-13

I am using the following fragment to show an onboarding screen on the first launch of the application. Should I inflate my layout in onCreateView or in onViewCreated? I don't quite understand how to decide on this. Also, do I need to create a ViewModel for my code?

class OnBoardingFragment : Fragment() {

    private lateinit var viewPager: ViewPager
    private lateinit var dotsLayout: LinearLayout
    private lateinit var sliderAdapter: SliderAdapter
    private lateinit var dots: Array<TextView?>
    private lateinit var letsGetStarted: Button
    private lateinit var next: Button
    private lateinit var animation: Animation
    private var currentPos: Int = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val navOptions = NavOptions.Builder().setPopUpTo(R.id.onBoardingFragment, true).build()
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_onboarding, container, false)

    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        viewPager = view.findViewById(R.id.slider);
        dotsLayout = view.findViewById(R.id.dots);
        letsGetStarted = view.findViewById(R.id.get_started_btn);
        next = view.findViewById(R.id.next_btn)

        sliderAdapter = SliderAdapter(requireContext())
        viewPager.adapter = sliderAdapter;

        addDots(0);
        viewPager.addOnPageChangeListener(changeListener);

        next.setOnClickListener {
            viewPager.currentItem = currentPos   1
        }
        letsGetStarted.setOnClickListener {
            findNavController().navigate(R.id.action_onBoardingFragment_to_loginFragment)
        }
    }

    private fun addDots(position: Int) {
        dots = arrayOfNulls(2)
        dotsLayout.removeAllViews();

        for (i in dots.indices) {
            dots[i] = TextView(requireContext())
            dots[i]!!.text = HtmlCompat.fromHtml("&#8226;", HtmlCompat.FROM_HTML_MODE_LEGACY)
            dots[i]!!.setTextColor(
                ContextCompat.getColor(
                    requireContext(),
                    android.R.color.darker_gray
                )
            )
            dots[i]!!.textSize = 35F
            dotsLayout.addView(dots[i])
        }
        if (dots.isNotEmpty()) {
            dots[position]!!.setTextColor(
                ContextCompat.getColor(
                    requireContext(),
                    R.color.wine_red
                )
            )
        }
    }

    private var changeListener: ViewPager.OnPageChangeListener =
        object : ViewPager.OnPageChangeListener {
            override fun onPageScrolled(
                position: Int,
                positionOffset: Float,
                positionOffsetPixels: Int
            ) {
            }

            override fun onPageSelected(position: Int) {
                addDots(position)
                currentPos = position
                animation =
                    AnimationUtils.loadAnimation(requireContext(), android.R.anim.fade_in)
                if (position == 0) {
                    letsGetStarted.visibility = View.INVISIBLE
                    next.animation = animation
                    next.visibility = View.VISIBLE
                } else {
                    letsGetStarted.animation = animation
                    letsGetStarted.visibility = View.VISIBLE
                    next.visibility = View.INVISIBLE
                }
            }

            override fun onPageScrollStateChanged(state: Int) {}
        }

}`

CodePudding user response:

The Android framework calls Fragment's onCreateView to create the view object hierarchy. Therefore, it's correct to inflate the layout here as you did.

onViewCreated is called afterwards, usually you find views and setup them. So, your code is ok.

Regarding the ViewModel, in your sample code you're just configuring the UI so you won't need it. If instead, you need to obtain some data from an API service, transform it, show the states of "loading data", "data retrieved" and "there was an error retrieving data", then you would like not to do those things in the fragment and you could consider using an MVVM approach.

Some references:

  • Related