简体   繁体   English

错误:lateinit 属性 recyclerViewAdapter 尚未初始化

[英]Error: lateinit property recyclerViewAdapter has not been initialized

I'm try to initialize recyclerView and ViewModel in onCreate in fragment and get error lateinit property recyclerViewAdapter has not been initialized我尝试在片段的onCreate中初始化 recyclerView 和 ViewModel 并得到错误lateinit property recyclerViewAdapter has not been initialized

class ListFragment : Fragment() {

    private val recyclerView: RecyclerView? = activity?.findViewById(R.id.recyclerView)

    private lateinit var recyclerViewAdapter: RecyclerViewAdapter

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

        initRecyclerView()
        initViewModel()
    }

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

    private fun initRecyclerView() {
        recyclerView?.apply {
            layoutManager = LinearLayoutManager(context)
            val decoration = DividerItemDecoration(context, DividerItemDecoration.VERTICAL)
            addItemDecoration(decoration)
            recyclerViewAdapter = RecyclerViewAdapter()
            adapter = recyclerViewAdapter
        }
    }

    private fun initViewModel() {
        val viewModel = ViewModelProvider(this)[MainActivityViewModel::class.java]
        lifecycleScope.launchWhenCreated {
            viewModel.getListData().collectLatest {
                recyclerViewAdapter.submitData(it)
            }
        }
    }
}

Here's where you went wrong:这是你出错的地方:

private val recyclerView: RecyclerView? = activity?.findViewById(R.id.recyclerView)

The above property will be null because activity is null at instantiation time of the Fragment, and you are using activity?.上述属性将为 null,因为在片段实例化时activity为 null,而您正在使用activity?. so you are initializing it as null .所以你将它初始化为null

Then in initRecyclerView() , you are using recyclerView?.apply , so nothing in the lambda will be executed because recyclerView is null. Therefore, the property recyclerViewAdapter is never set, so when it is first accessed (in initViewModel() ), it will throw UnitializedPropertAccessException and crash.然后在initRecyclerView()中,你正在使用recyclerView?.apply ,所以 lambda 中的任何内容都不会被执行,因为recyclerView是 null。因此,属性recyclerViewAdapter永远不会被设置,所以当它被第一次访问时(在initViewModel()中),它将抛出 UnitializedPropertAccessException 并崩溃。

You must not initialize a Fragment's view properties at the declaration site, because a Fragment is initialized before it is has any view or is attached to any Activity.您不能在声明站点初始化 Fragment 的视图属性,因为 Fragment 在它具有任何视图或附加到任何 Activity 之前被初始化。 Also, the same Fragment instance might be reused but have a new view and Activity instance, so you should make sure you are re-assigning these properties every time there is a new view.此外,同一个 Fragment 实例可能会被重用,但有一个新的视图和 Activity 实例,因此您应该确保每次有新视图时都重新分配这些属性。

Also, don't initialize views in onCreate() , because it happens before your onCreateView() , so there will be no view to find.另外,不要在onCreate()中初始化视图,因为它发生在你的onCreateView()之前,所以将找不到视图。 You should rarely ever need to use onCreate() in a Fragment.您应该很少需要在 Fragment 中使用onCreate() Use onViewCreated() instead.请改用onViewCreated()

And if the recycler view is in your Fragment layout, you should search the Fragment's view for the RecyclerView instead of searching up in the Activity.如果回收站视图在您的 Fragment 布局中,您应该在 Fragment 的视图中搜索 RecyclerView,而不是在 Activity 中向上搜索。 The Activity still does not contain the Fragment's views in onViewCreated() so it will fail to find the view. Activity 在onViewCreated()中仍然不包含 Fragment 的视图,因此它将无法找到视图。

Here's how to fix your code:以下是修复代码的方法:

class ListFragment : Fragment() {

    private lateinit var recyclerView: RecyclerView

    private lateinit var recyclerViewAdapter: RecyclerViewAdapter

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

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

        recyclerView = view.findViewById(R.id.recyclerView)

        initRecyclerView()
        initViewModel()
    }

    private fun initRecyclerView() {
        recyclerView.apply {
            layoutManager = LinearLayoutManager(context)
            val decoration = DividerItemDecoration(context, DividerItemDecoration.VERTICAL)
            addItemDecoration(decoration)
            recyclerViewAdapter = RecyclerViewAdapter()
            adapter = recyclerViewAdapter 
        }
    }

    private fun initViewModel() {
        //...
    }
}

The above technically leaks your views when the fragment is detached.当片段分离时,上面的技术在技术上泄露了你的观点。 You could avoid this by using custom getters so you aren't caching references to the views.您可以通过使用自定义 getter 来避免这种情况,这样您就不会缓存对视图的引用。 Also, you can eliminate onCreateView by passing your layout ID directly to the Fragment super-constructor.此外,您可以通过将布局 ID 直接传递给 Fragment 超级构造函数来消除onCreateView So here's how I would write this class:所以我会这样写这个 class:

class ListFragment : Fragment(R.layout.fragment_list) {

    private val recyclerView: RecyclerView
        get() = requireView().findViewById(R.id.recyclerView)

    private val recyclerViewAdapter: RecyclerViewAdapter
        get() = recyclerView.adapter as RecyclerViewAdapter

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

        initRecyclerView()
        initViewModel()
    }

    private fun initRecyclerView() {
        recyclerView.apply {
            layoutManager = LinearLayoutManager(context)
            val decoration = DividerItemDecoration(context, DividerItemDecoration.VERTICAL)
            addItemDecoration(decoration)
            adapter = RecyclerViewAdapter()
        }
    }

    private fun initViewModel() {
        //...
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 lateinit property has not been initialized 错误发生 - lateinit property has not been initialized error occur lateinit 属性 NotaViewModel 尚未初始化错误 - lateinit property NotaViewModel has not been initialized Error lateinit 属性尚未初始化 - lateinit property has not been initialized 在 onCreateView 中初始化的变量出现“Lateinit 属性尚未初始化”错误 - “Lateinit property has not been initialized” error on a variable initialized in onCreateView 我无法解决这个错误“lateinit property dataBinding has not been initialized” - I cant solve this error "lateinit property dataBinding has not been initialized" Hilt 和 WorkManager 错误:lateinit 属性 WorkerFactory 尚未初始化 - Hilt and WorkManager error : lateinit property WorkerFactory has not been initialized 如何在 kotlin 中初始化 lateinit 属性。 错误“kotlin.UninitializedPropertyAccessException:lateinit 属性学生尚未初始化” - How to initialize lateinit property in kotlin. error "kotlin.UninitializedPropertyAccessException: lateinit property student has not been initialized" lateinit 属性 ABC 尚未初始化 - lateinit property ABC has not been initialized lateinit 属性 llMain(RecyclerView) 尚未初始化 - lateinit property llMain(RecyclerView) has not been initialized lateinit 属性 providerFactory 尚未初始化 - lateinit property providerFactory has not been initialized
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM