Error: lateinit property recyclerViewAdapter has not been initialized
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)
上面的 属性 将为空,因为 activity
在 Fragment 的实例化时为空,而您正在使用 activity?.
所以您将其初始化为 null
.
然后在 initRecyclerView()
中,您使用的是 recyclerView?.apply
,因此不会执行 lambda 中的任何内容,因为 recyclerView
为空。因此,属性 recyclerViewAdapter
永远不会被设置,所以当它第一次访问时(在 initViewModel()
中),它会抛出 UnitializedPropertAccessException 并崩溃。
您不得在声明站点初始化 Fragment 的视图属性,因为 Fragment 在具有任何视图或附加到任何视图之前就已初始化 Activity。此外,同一个 Fragment 实例可能会被重复使用,但有一个新的视图和 Activity 实例,所以你应该确保每次有一个新视图时你都是 re-assigning 这些属性。
此外,不要在 onCreate()
中初始化视图,因为它发生在您的 onCreateView()
之前,因此将找不到视图。您应该很少需要在片段中使用 onCreate()
。请改用 onViewCreated()
。
如果回收站视图在您的 Fragment 布局中,您应该在 Fragment 的视图中搜索 RecyclerView,而不是在 Activity 中向上搜索。 Activity 仍然不包含片段在 onViewCreated()
中的视图,因此它将无法找到视图。
修复代码的方法如下:
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 直接传递给片段 super-constructor 来消除 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() {
//...
}
}
我尝试在 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)
上面的 属性 将为空,因为 activity
在 Fragment 的实例化时为空,而您正在使用 activity?.
所以您将其初始化为 null
.
然后在 initRecyclerView()
中,您使用的是 recyclerView?.apply
,因此不会执行 lambda 中的任何内容,因为 recyclerView
为空。因此,属性 recyclerViewAdapter
永远不会被设置,所以当它第一次访问时(在 initViewModel()
中),它会抛出 UnitializedPropertAccessException 并崩溃。
您不得在声明站点初始化 Fragment 的视图属性,因为 Fragment 在具有任何视图或附加到任何视图之前就已初始化 Activity。此外,同一个 Fragment 实例可能会被重复使用,但有一个新的视图和 Activity 实例,所以你应该确保每次有一个新视图时你都是 re-assigning 这些属性。
此外,不要在 onCreate()
中初始化视图,因为它发生在您的 onCreateView()
之前,因此将找不到视图。您应该很少需要在片段中使用 onCreate()
。请改用 onViewCreated()
。
如果回收站视图在您的 Fragment 布局中,您应该在 Fragment 的视图中搜索 RecyclerView,而不是在 Activity 中向上搜索。 Activity 仍然不包含片段在 onViewCreated()
中的视图,因此它将无法找到视图。
修复代码的方法如下:
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 直接传递给片段 super-constructor 来消除 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() {
//...
}
}