繁体   English   中英

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

[英]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)
            }
        }
    }
}

这是你出错的地方:

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

上述属性将为 null,因为在片段实例化时activity为 null,而您正在使用activity?. 所以你将它初始化为null

然后在initRecyclerView()中,你正在使用recyclerView?.apply ,所以 lambda 中的任何内容都不会被执行,因为recyclerView是 null。因此,属性recyclerViewAdapter永远不会被设置,所以当它被第一次访问时(在initViewModel()中),它将抛出 UnitializedPropertAccessException 并崩溃。

您不能在声明站点初始化 Fragment 的视图属性,因为 Fragment 在它具有任何视图或附加到任何 Activity 之前被初始化。 此外,同一个 Fragment 实例可能会被重用,但有一个新的视图和 Activity 实例,因此您应该确保每次有新视图时都重新分配这些属性。

另外,不要在onCreate()中初始化视图,因为它发生在你的onCreateView()之前,所以将找不到视图。 您应该很少需要在 Fragment 中使用onCreate() 请改用onViewCreated()

如果回收站视图在您的 Fragment 布局中,您应该在 Fragment 的视图中搜索 RecyclerView,而不是在 Activity 中向上搜索。 Activity 在onViewCreated()中仍然不包含 Fragment 的视图,因此它将无法找到视图。

以下是修复代码的方法:

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() {
        //...
    }
}

当片段分离时,上面的技术在技术上泄露了你的观点。 您可以通过使用自定义 getter 来避免这种情况,这样您就不会缓存对视图的引用。 此外,您可以通过将布局 ID 直接传递给 Fragment 超级构造函数来消除onCreateView 所以我会这样写这个 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM