Свойство lateinit viewModel не инициализируется при вызове метода по щелчку из адаптера RecyclerView - PullRequest
0 голосов
/ 05 февраля 2020

Я пытаюсь удалить заметку из базы данных комнат, вызывая метод, когда пользователь долго нажимает на заметку. Я настроил onLongClickListener на адаптере RView:

viewHolder.itemView.setOnCLickListener{
            NotesFragment().deleteSingleNote(notesID)
        }

В NotesFragment, метод выглядит следующим образом:

fun deleteSingleNote(notesID: Long) {
        notesFragmentViewModel.deleteSingleNoteFromDB(notesID)
    }

и в ViewModel метод удаляет заметку через сопрограмму.

Приложение вылетает при длинном щелчке, говоря, что lateinit notesFragmentViewModel не инициализировалась, указывая на строку onLongCLickListener и строку NotesFragment, которые я вставил выше.

Дело в том, что примечания заполняются на экране через переменную NotesFragmentViewModel LiveData, которая содержит все примечания, поэтому ViewModel очень сильно инициализируется Когда я долго нажимал на элемент.

Я попытался инициализировать ViewModel на адаптере, но я получил исключение, связанное с тем, что ViewModel не разрешено инстанцировать на чем-то, кроме фрагмента / действия.

Это мой первый пост на SOverflow, поэтому, пожалуйста, дайте мне знать ш, если я сделал что-то не так

1 Ответ

0 голосов
/ 05 февраля 2020

Внутри OnClickListener вы хотите получить доступ к экземпляру NotesFragment, который отображается в данный момент. Но с NotesFragment() вы создаете новый экземпляр NotesFragment. Поскольку он не будет прикреплен ни к одному Activity, весьма вероятно, что свойство notesFragmentViewModel нового экземпляра не было инициализировано.

Поэтому, чтобы избежать Exception , вы должен получить доступ к правильному экземпляру из NotesFragment. Вы можете ввести параметр типа NotesFragment в конструктор RecyclerView.Adapter, но это считается плохой практикой.

Лучше позволить классу адаптера иметь интерфейс (назовем его ListItemClickedListener) и конструктор, который требует экземпляр ListItemClickedListener в качестве параметра.

interface ListItemClickedListener{
    fun singleNoteLongClicked(notesID: Long)
}

Тогда вы можете либо NotesFragment реализовать ListItemClickedListener и передать себя адаптеру, либо использовать анонимный локальный экземпляр ListItemClickedListener.

Внутри адаптера:

viewHolder.itemView.setOnCLickListener{
    listItemClickListener.singleNoteLongClicked(notesID)
}

In NotesFragment:

override fun singleNoteLongClicked(notesID: Long){
    this@NotesFragment.deleteSingleNote(notesID)
} 

См., Например, этот пост для реализации этого шаблона.

...