Элемент RecyclerView не обновляется с помощью LiveData - PullRequest
0 голосов
/ 17 марта 2020

У меня есть приложение, использующее привязку данных, liveata, room, kotlin koroutines, viewmodel, компонент навигации и кинжал. У меня есть одно действие и два фрагмента.

ListFragment: показать в окне рециркулятора список элементов.

DetalFragment: показать детали элемента и может обновить некоторые поля элемента с сохранением кнопка.

Проблема в том, что когда я обновляю некоторые поля из фрагмента детали, изменения не видны в фрагменте списка, но при прокрутке вниз и вверх изменения становятся видимыми.

ListFragment :

 @Inject
lateinit var viewModelFactory: ViewModelProvider.Factory
val viewModel: ListViewModel by viewModels {
    viewModelFactory
}

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    val bindings = ListFragmentBinding.inflate(inflater, container, false).apply {
        viewmodel = viewModel
    }
    bindings.lifecycleOwner = this
    adapter = ItemsAdapter()
    bindings.recyclerView.adapter = adapter
    viewModel.items.observe(
        viewLifecycleOwner,
        Observer { adapter.submitList(it)})
    return bindings.root
}

ListViewModel:

var items: LiveData<PagedList<Item>> = repository.items

Репозиторий:

val items<PagedList<Item>>
get()=itemDao.getAllItemsPaged().toLiveData(pageSize=50)
fun getItemFlow(id: String): Flow<Item> = itemDao.getItemFlow(id)
suspend fun updateItem(item: Item) {
   itemDao.updateItem(item)
}

ItemDao:

 @Query("SELECT * FROM item")
fun getAllItemsPaged(): DataSource.Factory<Int,Item>
@Query("SELECT * FROM itemWHERE id=:id")
fun getItemFlow(id:String):Flow<Item>
@Update
suspend fun updateItem(item:Item)

ItemFragment:

@Inject
lateinit var viewModelFactory: ViewModelProvider.Factory
val viewModel: ItemViewModel by viewModels {
    viewModelFactory
}
override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    viewModel.loadItem(args.itemId)
    val bindings = ItemFragmentBinding.inflate(inflater, container, false).apply {
        viewmodel = viewModel
        buttonSave.setOnClickListener{viewModel. viewModelScope.launch {
        viewModel.saveItem()
        findNavController().navigateUp()
    }}

    }

    bindings.lifecycleOwner = this
    return bindings.root
}

ItemViewModel:

var item: LiveData<Item>? = null

fun loadItem(id: String) {
    viewModelScope.launch {
        item = repository.getItemFlow(id).asLiveData()
    }
}

suspend fun saveItem() {
    item!!.value!!.someField = "hi"
    repository.updateItem(item!!.value!!)
}

1 Ответ

0 голосов
/ 18 марта 2020

Проблема в адаптере товаров. Адаптеру требуется правильная реализация DiffUtil.ItemCallback

В этом случае:

private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<Contador>() {
// The ID property identifies when items are the same.
override fun areItemsTheSame(oldItem: Contador, newItem: Contador) =
    oldItem.id == newItem.id

// Check the properties that can change, or implements the equals method in Item class
override fun areContentsTheSame(
    oldItem: Item, newItem: Item) = oldItem.someField == newItem.someField

}

...