Ошибка lateinit property binding has not been initialized
Хочу перенести приложение для заметок из Activity в Fragment. В Activity все работало без ошибок, но как перенес начались проблемы. При запуске и выборе фрагмента приложение вылетает и выдает lateinit property binding has not been initialized, как это исправить?
class PlannedEvFragment : Fragment(R.layout.fragment_planned_ev){
private lateinit var binding: FragmentPlannedEvBinding
private lateinit var noteViewModel: NoteViewModel
private lateinit var adapter: NoteRecyclerViewAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val dao = NoteDatabase.getInstance(activity!!.application).noteDAO
val repository = NoteRepository(dao)
val factory = NoteViewModelFactory(repository)
noteViewModel = ViewModelProvider(this, factory).get(NoteViewModel::class.java)
binding.noteViewModel = noteViewModel <-- на этой строчке выдает ошибку
binding.lifecycleOwner = this
displayNoteList()
initRecyclerView()
nnoteViewModel.message.observe(this, Observer {
it.getContentIfNotHandled()?.let {
Toast.makeText(activity!!.application, it, Toast.LENGTH_SHORT).show()
}
})
}
private fun initRecyclerView(){
adapter = NoteRecyclerViewAdapter({ selectedItem: Note -> listItemClicked(selectedItem) })
binding.noteRecyclerView.layoutManager = LinearLayoutManager(context)
binding.noteRecyclerView.adapter = adapter
displayNoteList()
}
private fun displayNoteList(){
noteViewModel.notes.observe(this, Observer {
Log.i("MYTAG", it.toString())
adapter.setList(it)
adapter.notifyDataSetChanged()
})
}
private fun listItemClicked(note: Note){
noteViewModel.initUpdateAndDelete(note)
}
}
Фрагмент:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="noteViewModel"
type="com.example.taskmanager.view.NoteViewModel" />
</data>
Ответы (2 шт):
Я не очень хорошо знаком с Data Binding, но, думаю я знаю где ваша проблема.
Ошибка lateinit property binding has not been initialized говорит о том, что есть некоторое поле (в вашем случае binding которое не инициализированно, т.е. null).
Тут есть 2 варианта:
Либо вы в принципе не вызвали методы инициализации
bindingв коде. Я их не вижу, поэтому вполне вероятно, что ваша проблема лежит здесь.Но тут может быть такое, что система делает это под капотом (это к тому, что я не знаю как правильно должны инициализироваться биндинги в Data Bindnig). Если вы говорите, что данный код работал в
Activityуспешно, то скорее всего вам нужно перенести всю инициализацию (в частности любые вызовыbinding) любой колбек жизненного цикла фрагмента начиная сonViewCreated()или более поздний.Связано это с тем, что в Activity ваша View вам доступна уже в методе
onCreate()после вызоваsetContentView()и там ваш биндинг мог обратиться коView. Во фрагменте в методеonCreate()никакойViewеще не существует, макет раздувается в методеonCreateView()и готов к использованию уже вonViewCreated()
Необходимо добавить метод onCreateView(). В нем инициализировать binding :
override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { binding = DataBindingUtil.inflate(inflater, layoutId, container, false) return binding.root }Необходимо вынести логику из метода onCreate в метод onViewCreated()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val dao = NoteDatabase.getInstance(activity!!.application).noteDAO val repository = NoteRepository(dao) val factory = NoteViewModelFactory(repository) noteViewModel = ViewModelProvider(this, factory).get(NoteViewModel::class.java) binding.noteViewModel = noteViewModel binding.lifecycleOwner = this displayNoteList() initRecyclerView() nnoteViewModel.message.observe(this, Observer { it.getContentIfNotHandled()?.let { Toast.makeText(activity!!.application, it, Toast.LENGTH_SHORT).show() } }) }