Я новичок в архитектуре MVVM, и я немного смущен тем, почему я не могу заставить объект Livedata обновляться до recyclerview во фрагменте. Используя журнал в разных местах приложения, я обнаружил, что таблица sqlite обновляется, она просто не отображает данные.
Это простое приложение для создания заметок, и я только пытаюсь отобразить заголовки из таблицы sqlite в данный момент. Об остальном я могу побеспокоиться позже.
Любая помощь приветствуется, я новичок в комнате (и sqlite в целом), поэтому большая часть кода основана на Room With a View
Я могу предоставить больше кода, если необходимо, я просто стараюсь сделать его как можно более простым, чтобы кто-то посмотрел!
TitlesFragment
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
class TitlesFragment : Fragment(){
private lateinit var noteViewModel: NoteViewModel
private lateinit var note: Note
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val rootView = inflater.inflate(R.layout.fragment_titles, container, false)
val adapter = this.context?.let { NoteListAdapter(it) }
noteViewModel = ViewModelProvider(this).get(NoteViewModel::class.java)
noteViewModel.allNotes.observe(viewLifecycleOwner, Observer { notes ->
notes?.let { adapter?.setNotes(it) }
})
val recyclerView = rootView.findViewById< RecyclerView>(R.id.titlesrecyclerview) as RecyclerView
recyclerView.layoutManager = LinearLayoutManager(activity)
recyclerView.adapter = this.context?.let { NoteListAdapter(it) }
return rootView
}
fun receiveNote(note: Note) {
this.note = note
noteViewModel.insert(this.note)
}
}
NoteListAdapter
import android.content.Context
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.RecyclerView
class NoteListAdapter internal constructor(
context: Context
) : RecyclerView.Adapter<NoteListAdapter.NoteViewHolder>() {
private val inflater: LayoutInflater = LayoutInflater.from(context)
private var notes = emptyList<Note>()
inner class NoteViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val noteItemView: TextView = itemView.findViewById(R.id.title_box)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NoteViewHolder {
val itemView = inflater.inflate(R.layout.fragment_titles, parent, false)
return NoteViewHolder(itemView)
}
override fun onBindViewHolder(holder: NoteViewHolder, position: Int) {
val current = notes[position]
holder.noteItemView.text = current.note
}
internal fun setNotes(notes: List<Note>) {
this.notes = notes
notifyDataSetChanged()
}
override fun getItemCount() = notes.size
}
NoteViewModel
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class NoteViewModel (application: Application) : AndroidViewModel(application) {
private val repository: NoteRepository
val allNotes: LiveData<List<Note>>
init {
val notesDao = NoteDatabase.getDatabase(application, viewModelScope).noteDao()
repository = NoteRepository(notesDao)
allNotes = repository.allNotes
}
fun insert(note: Note) = viewModelScope.launch(Dispatchers.IO) {
repository.insert(note)
}
}
NoteDatabase
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.sqlite.db.SupportSQLiteDatabase
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
@Database(entities = arrayOf(Note::class), version = 1, exportSchema = false)
abstract class NoteDatabase : RoomDatabase() {
abstract fun noteDao(): NoteDao
companion object {
@Volatile
private var INSTANCE: NoteDatabase? = null
fun getDatabase(context: Context, scope: CoroutineScope): NoteDatabase {
val tempInstance = INSTANCE
if (tempInstance != null) {
return tempInstance
}
synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
NoteDatabase::class.java,
"note_database"
).addCallback(NoteDatabaseCallback(scope)).build()
INSTANCE = instance
return instance
}
}
}
private class NoteDatabaseCallback(
private val scope: CoroutineScope) : RoomDatabase.Callback() {
override fun onOpen(db: SupportSQLiteDatabase) {
super.onOpen(db)
INSTANCE?.let { database ->
scope.launch {
populateDatabase(database.noteDao())
}
}
}
suspend fun populateDatabase(noteDao: NoteDao) {
noteDao.deleteAll()
var note = Note("test1", "hello")
noteDao.insert(note)
note = Note("test2", "world")
noteDao.insert(note)
}
}
}
NoteRepository
import androidx.lifecycle.LiveData
class NoteRepository(private val noteDao: NoteDao) {
val allNotes: LiveData<List<Note>> = noteDao.getAllNotes()
suspend fun insert(note: Note) {
noteDao.insert(note)
}
}
NoteDao
import androidx.lifecycle.LiveData
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
@Dao
interface NoteDao {
@Query("SELECT * from note_table")
fun getAllNotes(): LiveData<List<Note>>
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(note: Note)
@Query("DELETE FROM note_table")
suspend fun deleteAll()
}