[英]lateinit property has not been initialized error occur
[英]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.