【问题标题】:Android Recyclerview OnBindViewHolder update ui only when scrollAndroid Recyclerview OnBindViewHolder 仅在滚动时更新 ui
【发布时间】:2020-10-16 03:14:15
【问题描述】:

当我打开应用程序时,保存 ImageView 可以工作,但是当我单击保存时它不会更新保存的 ImageView ,它仅在我滚动 recyclerview 并滚动回该位置时才有效。

如果它在收藏列表中,我会使用 Room 数据库更新回收站视图项

class AdapterHomeMovie(
    private val databaseDao: DatabaseDao,
    private val onClick: (Movie) -> Unit,
    private val onSave: (Movie) -> Unit
) : ListAdapter<Movie, MovieViewHolder>(DiffCallBack) {
override fun onBindViewHolder(holder: MovieViewHolder, position: Int) {
    val item = getItem(position)

    val scope = CoroutineScope(Dispatchers.IO)

    holder.bind(item, onSave)
    holder.itemView.setOnClickListener { onClick(item) }

    if (databaseDao.isSaved(item.title)) holder.imgSave.setImageResource(R.drawable.ic_save_yellow)
    else holder.imgSave.setImageResource(R.drawable.ic_save_normal)

    holder.imgSave.setOnClickListener {
        scope.launch {
            if (databaseDao.isSaved(item.title)) {
                databaseDao.deleteSaveMovie(item.title)
            } else {
                databaseDao.insertDownloading(
                    SaveMovie(item.title, item.thumbnail, item.id, item.sid, item.rating.toLong(), System.currentTimeMillis())
                )
            }
        }
    }
}


override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MovieViewHolder {
    return MovieViewHolder(ItemMovieBinding.inflate(LayoutInflater.from(parent.context), parent, false))
}

companion object{
    val DiffCallBack = object : DiffUtil.ItemCallback<Movie>() {
        override fun areItemsTheSame(oldItem: Movie, newItem: Movie): Boolean {
            return oldItem.title == newItem.title
        }

        override fun areContentsTheSame(oldItem: Movie, newItem: Movie): Boolean {
            return oldItem == newItem
        }

        override fun getChangePayload(oldItem: Movie, newItem: Movie): Any? {
            return super.getChangePayload(oldItem, newItem)
        }
    }
}
} 

【问题讨论】:

    标签: android android-recyclerview


    【解决方案1】:

    更新数据时必须通知位置的项目发生了变化 holder.imgSave.setOnClickListener {

    scope.launch {
            if (databaseDao.isSaved(item.title)) {
                databaseDao.deleteSaveMovie(item.title)
            } else {
                databaseDao.insertDownloading(
                    SaveMovie(item.title, item.thumbnail, item.id, item.sid, item.rating.toLong(), System.currentTimeMillis())
                )
            }
            notifyItemChanged(position)
        }
    }
    

    【讨论】:

      【解决方案2】:

      您可以使用将List 包裹在LiveData 中。实际上 Room 支持LiveData 开箱即用。

      我是你的片段,你可以这样做:

      val liveMovieList : LiveData<List<Movie>> = // fetch data from dao
      
      ...
      
      liveMovieList.observe(viewLifecycleOwner, Observer { movies ->
        yourListAdapter.submitList(movies);
      });
      

      在你的 Dao 中,你可以像这样返回LiveData

      @Query("SELECT * from movie_table")
      fun getAllMovies() : LiveData<List<Movie>>
      

      要使用LiveData,您需要在应用级构建gradle文件中添加以下依赖项:

      
      dependencies {
          def lifecycle_version = "2.2.0"
          def arch_version = "2.1.0"
      
          ...
      
          // LiveData
          implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
      }
      

      为什么要使用 LiveData

      • 确保您的 UI 与您的数据状态相匹配
      • 没有内存泄漏
      • 没有因活动停止而导致的崩溃
      • 不再需要手动处理生命周期
      • 始终保持最新数据
      • 正确的配置更改
      • 共享资源

      您可以在LiveData Overview阅读更多内容

      【讨论】:

      • 我知道,但是我在回收站中使用的列表来自 firebase 而不是来自 Room。无论如何感谢您的回答
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-04
      • 1970-01-01
      • 1970-01-01
      • 2021-10-29
      • 2018-06-01
      • 1970-01-01
      相关资源
      最近更新 更多