Не обновляется recyclerview с cursor

Я написал приложение учебное CRUD приложение при помощи room и mvvm архитектуре, но поставили задачу добавить управление бд ещё при помощи cursor. И проблема возникла что при любых операциях первоначальный список не обновляется, как при room. Как я понимаю в room под капотом реализован потерн наблюдатель. Может кто подскажет или скинет похожий пример.

const val FIRST_COLUMN = "id"
const val SECOND_COLUMN = "name"
const val THIRD_COLUMN = "breed"
const val FOURTH_COLUMN = "age"
const val FIFTH_COLUMN = "created"

const val CATS_DATABASE = "CATS_DATABASE"
const val TABLE_NAME = "cats_table"
private const val DATABASE_VERSION = 1
private const val CREATE_TABLE_SQL = "CREATE TABLE IF NOT EXISTS $TABLE_NAME" +
        " ($FIRST_COLUMN INTEGER PRIMARY KEY AUTOINCREMENT, $SECOND_COLUMN VARCHAR(50), $THIRD_COLUMN VARCHAR(50), " +
        "$FOURTH_COLUMN INTEGER, $FIFTH_COLUMN INTEGER);"

typealias CatListener = (users: List<Cat>) -> Unit

class CursorDataBase(context: Context): SQLiteOpenHelper(
    context,
    CATS_DATABASE,
    null,
    DATABASE_VERSION
) {

    private val listOfTopics = mutableListOf<Cat>()

    private val listeners = mutableSetOf<CatListener>()

    override fun onCreate(db: SQLiteDatabase) {
        try {
            db.execSQL(CREATE_TABLE_SQL)
        } catch (exception: SQLException) {
            Log.e("onCreate", "Exception while trying to create database", exception)
        }
    }

    override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
        Log.d("onUpgrade", "onUpgrade called")
    }

    private fun getCursorWithTopicsRead(): Cursor {
        return readableDatabase.rawQuery("SELECT * FROM $TABLE_NAME", null)
    }

    fun getAll() = flow<List<Cat>> {
        getCursorWithTopicsRead().use { cursor ->
            if (cursor.moveToFirst()) {
                do {
                    val id = cursor.getInt(cursor.getColumnIndex(FIRST_COLUMN))
                    val name = cursor.getString(cursor.getColumnIndex(SECOND_COLUMN))
                    val breed = cursor.getString(cursor.getColumnIndex(THIRD_COLUMN))
                    val age = cursor.getInt(cursor.getColumnIndex(FOURTH_COLUMN))
                    val created = cursor.getLong(cursor.getColumnIndex(FIFTH_COLUMN))
                    val person = Cat(id, name, breed, age, created)
                    listOfTopics.add(person)
                    emit(listOfTopics)
                    Log.d("getAll", listOfTopics.size.toString())
                } while (cursor.moveToNext())
            }
            cursor.close()
        }
    }

    suspend fun save(cat: Cat) {
        val values = ContentValues()
        values.put(SECOND_COLUMN, cat.name)
        values.put(THIRD_COLUMN, cat.breed)
        values.put(FOURTH_COLUMN, cat.age)
        values.put(FIFTH_COLUMN, cat.created)
        writableDatabase.insert(TABLE_NAME, null, values)
    }

    suspend fun delete(cat: Cat): Int {
        writableDatabase.delete(TABLE_NAME, "id = ${cat.id}", null)
        notifyChanges()
        return 1
    }

    suspend fun update(cat: Cat){
        val updatedValues = ContentValues()
        updatedValues.put(SECOND_COLUMN, cat.name)
        updatedValues.put(THIRD_COLUMN, cat.breed)
        updatedValues.put(FOURTH_COLUMN, cat.age)
        val where = "id = ${cat.id}"
        writableDatabase.update(TABLE_NAME, updatedValues, where, null)
        notifyChanges()
    }


    fun addListener(listener: CatListener) {
        listener.invoke(listOfTopics)
        listeners.add(listener)

    }

    fun removeListener(listener: CatListener) {
        listeners.remove(listener)

    }

    private fun notifyChanges() {
        listeners.forEach { it.invoke(listOfTopics) }
    }
}

viewModel

    class CatListViewModel(
    private val preferencesManager: PreferencesManager,
    private val repository: CursorDataBase): ViewModel() {

//    private val repository = get()


//    val preferencesFlow: Flow<FilterPreferences> = preferencesManager.orderFlow

    @ExperimentalCoroutinesApi
    private val preferencesFlow: Flow<String> = preferencesManager.orderFlow2


    //    https://habr.com/ru/post/529944/
    private val catEventChannel = Channel<CatEvent>()
    val catEvent: Flow<CatEvent> = catEventChannel.receiveAsFlow()

//    @ExperimentalCoroutinesApi
//    private val catFlow = preferencesFlow.flatMapLatest { filterPreferences ->
//        repository.getTasks(filterPreferences)
//    }

    private val catFlow = repository.getAll()

    fun onAddNewCatClick() = viewModelScope.launch {
        catEventChannel.send(CatEvent.NavigateToAddCatFragment)
    }

    fun onTaskSwiped(cat: Cat) = viewModelScope.launch {
        repository.delete(cat)
        catEventChannel.send(CatEvent.ShowUndoDeleteTaskMessage(cat))
    }

    fun onUndoDeletedClick(cat: Cat) = viewModelScope.launch {
        repository.save(cat)
    }

    fun onSortOrderSelected(sortOrder: SortOrder) = viewModelScope.launch {
        preferencesManager.updateSortOrder(sortOrder)
    }

    fun onCatSelected(cat: Cat) = viewModelScope.launch {
        catEventChannel.send(CatEvent.NavigateToEditTaskScreen(cat))
    }

    fun onAddEditResult(result: Int) {
        when (result) {
            ADD_TASK_RESULT_OK -> showTaskSavedConfirmationMessage("кот добавлен")
            EDIT_TASK_RESULT_OK -> showTaskSavedConfirmationMessage("кот обнавлён")
        }
    }

    private fun showTaskSavedConfirmationMessage(s: String) = viewModelScope.launch {
        catEventChannel.send(CatEvent.ShowTaskSavedConfirmationMessage(s))
    }


    sealed class CatEvent {
        object NavigateToAddCatFragment : CatEvent()
        data class NavigateToEditTaskScreen(val cat: Cat) : CatEvent()
        data class ShowUndoDeleteTaskMessage(val cat: Cat) : CatEvent()
        data class ShowTaskSavedConfirmationMessage(val msg: String) : CatEvent()
    }

    @ExperimentalCoroutinesApi
    val cats: LiveData<List<Cat>> = catFlow.asLiveData()
}

фрагмент

class CatListFragment : Fragment(), CatAdapter.OnItemClickListener {

    private val viewModel: CatListViewModel by viewModels { factory() }

    private var _binding: CatListFragmentBinding? = null
    private val binding get() = _binding!!

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = CatListFragmentBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        val catAdapter = CatAdapter(this)


        binding.apply {
            recyclerViewCats.apply {
                adapter = catAdapter
                layoutManager = LinearLayoutManager(requireContext())
                setHasFixedSize(true)
                SwipeHelper(viewModel::onTaskSwiped).attachToRecyclerView(recyclerViewCats)
            }

            viewModel.cats.observe(viewLifecycleOwner) {
                catAdapter.submitList(it)
            }

            binding.fabAddCat.setOnClickListener {
                viewModel.onAddNewCatClick()
            }
        }


//            https://habr.com/ru/company/otus/blog/564050/
        viewLifecycleOwner.lifecycleScope.launchWhenStarted {
            viewModel.catEvent.collect { event ->
                when (event) {
                    is CatListViewModel.CatEvent.NavigateToAddCatFragment -> {
                        val action = CatListFragmentDirections.actionCatListFragmentToCatFragment(null, "Новый кот")
                        findNavController().navigate(action)
                    }

                    is CatListViewModel.CatEvent.ShowUndoDeleteTaskMessage -> {
                        Snackbar.make(requireView(), "Кот удалён", Snackbar.LENGTH_LONG)
                            .setAction("ОТМЕНИТЬ") {
                                viewModel.onUndoDeletedClick(event.cat)
                            }.show()
                    }

                    is CatListViewModel.CatEvent.NavigateToEditTaskScreen -> {
                        val action =
                            CatListFragmentDirections.actionCatListFragmentToCatFragment(event.cat, "Редактирование")
                        findNavController().navigate(action)
                    }

                    is CatListViewModel.CatEvent.ShowTaskSavedConfirmationMessage -> {
                        Snackbar.make(requireView(), event.msg, Snackbar.LENGTH_SHORT).show()
                    }
                }
            }
        }

        setFragmentResultListener("add_edit_request") { _, bundle ->
            val result = bundle.getInt("add_edit_result")
            viewModel.onAddEditResult(result)
        }

        setHasOptionsMenu(true)
    }

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        inflater.inflate(R.menu.menu_fragment_list_cat, menu)
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return when (item.itemId) {
            R.id.action_sort_by_name -> {
                viewModel.onSortOrderSelected(SortOrder.BY_NAME)
                true
            }
            R.id.action_sort_by_age -> {
                viewModel.onSortOrderSelected(SortOrder.BY_AGE)
                true
            }
            R.id.action_sort_by_date -> {
                viewModel.onSortOrderSelected(SortOrder.BY_DATE)
                true
            }

            else -> super.onOptionsItemSelected(item)
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }

    override fun onItemClick(cat: Cat) {
        viewModel.onCatSelected(cat)
    }
}

Ответы (0 шт):