[英]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.