Android Fragment中调用requireView()抛出「did not return a View from onCreateView() or this was called before onCreateView()」错误的原因咨询
Problem Description
I'm working on a project where the code has no syntax errors, but when building and running the app, I get the error "did not return a View from onCreateView() or this was called before onCreateView()" when executing viewPager2 = requireView().findViewById(R.id.vpager) in my MyFragment's onCreateView method. Here's my Fragment code:
class MyFragment : Fragment(R.layout.fragment_my) { lateinit var viewPager2: ViewPager2 lateinit var adapter: VideoAdapter override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { /**set find id*/ viewPager2 = requireView().findViewById(R.id.vpager) /**set database*/ val mDataBase = Firebase.database.getReference("videos") val options = FirebaseRecyclerOptions.Builder<VideoModel>() .setQuery(mDataBase,VideoModel::class.java) .build() /**set adapter*/ adapter = VideoAdapter(options) viewPager2.adapter = adapter return view } override fun onStart() { super.onStart() adapter.startListening() } override fun onStop() { super.onStop() adapter.stopListening() } }
Root Cause
Let's break down why this error pops up:
- You're using the
Fragment(R.layout.fragment_my)constructor, which automatically handles inflating your layout. When you overrideonCreateView, thesuper.onCreateView()call already returns the inflated view. - The critical issue is that you're calling
requireView()before returning the view fromonCreateView.requireView()is meant to fetch the Fragment's already attached view, but at this point in the lifecycle, the view hasn't been fully linked to the Fragment yet—sinceonCreateViewhasn't finished executing and returned the view. - On top of that, your current code returns
viewwithout properly initializing it from the super call, which adds to the lifecycle mismatch.
Fixes & Solutions
Solution 1: Use onViewCreated (Recommended)
The onViewCreated lifecycle method runs right after onCreateView returns the view, so the Fragment's view is fully attached and safe to interact with. This is the cleanest approach for view-related setup:
class MyFragment : Fragment(R.layout.fragment_my) { lateinit var viewPager2: ViewPager2 lateinit var adapter: VideoAdapter override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // Use the provided view parameter directly (no need for requireView()) viewPager2 = view.findViewById(R.id.vpager) // Initialize Firebase and adapter val mDataBase = Firebase.database.getReference("videos") val options = FirebaseRecyclerOptions.Builder<VideoModel>() .setQuery(mDataBase, VideoModel::class.java) .build() adapter = VideoAdapter(options) viewPager2.adapter = adapter } override fun onStart() { super.onStart() adapter.startListening() } override fun onStop() { super.onStop() adapter.stopListening() } }
Solution 2: Fix onCreateView to Use the Inflated View
If you prefer to keep initialization within onCreateView, first capture the view returned by super.onCreateView(), then use that view to find your ViewPager2:
class MyFragment : Fragment(R.layout.fragment_my) { lateinit var viewPager2: ViewPager2 lateinit var adapter: VideoAdapter override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { // Get the inflated view from the super call val view = super.onCreateView(inflater, container, savedInstanceState) // Use this view to find your ViewPager2 (no requireView() needed) viewPager2 = view!!.findViewById(R.id.vpager) // Initialize Firebase and adapter val mDataBase = Firebase.database.getReference("videos") val options = FirebaseRecyclerOptions.Builder<VideoModel>() .setQuery(mDataBase, VideoModel::class.java) .build() adapter = VideoAdapter(options) viewPager2.adapter = adapter return view } override fun onStart() { super.onStart() adapter.startListening() } override fun onStop() { super.onStop() adapter.stopListening() } }
Why Solution 1 is Preferred
onViewCreated is explicitly designed for post-view-creation setup. It separates layout inflation logic (handled by the Fragment(R.layout.fragment_my) constructor) from view initialization, making your code more organized and aligned with Android's Fragment lifecycle best practices.
内容的提问来源于stack exchange,提问作者user10991969

