【问题标题】:Android Recycleview DiffUtil doesn't work properlyAndroid Recyclerview DiffUtil 无法正常工作
【发布时间】:2021-03-02 07:19:12
【问题描述】:

我在我的应用程序中使用带有 diffutil 的回收视图。但是当我从另一个屏幕旋转或返回时,适配器会更新。为什么会这样?

这是我的视图模型

class FeedsViewModel() : ViewModel() {

    private val feedsRepository = FeedsRepository()
    val feedsLiveData: MutableLiveData<Resource<UserFeeds>> = MutableLiveData()
    init {
        val apiParams = HashMap<String, String>()
        apiParams["user_id"] = "1"
        getFeeds(apiParams,"123"
}
    fun getFeeds(apiParams: HashMap<String, String>, token: String) = viewModelScope.launch {
        feedsLiveData.postValue(Resource.Loading())
        val response = feedsRepository.getFeeds(apiParams, token)
        if (response.isSuccessful) {
            response.body()?.let { resultResponse ->
                feedsLiveData.postValue(Resource.Success(resultResponse))
            }
        } else {
            feedsLiveData.postValue(Resource.Error(response.message()))

        }
    }
}

我正在使用片段来显示它

  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        binding.recyclerViewFeeds.adapter = feedsAdapter
        viewModel.feedsLiveData.observe(viewLifecycleOwner, Observer { response ->
            when (response) {
                is Resource.Success -> {
                    binding.progressBar.visibility = View.GONE
                    response.data?.let { userFeeds ->
                        feedsAdapter.differ.submitList(userFeeds.userPosts.toList())
                        binding.nooFeeds.visibility = View.GONE
                    }
                is Resource.Error -> {....}
                is Resource.Loading -> {....}
            }
        })
    }

还有我的适配器

class FeedsAdapter(private val context: Context, private val itemClickListener: FeedsItemCallBack) :
    RecyclerView.Adapter<FeedsAdapter.MyViewHolder>() {
    class MyViewHolder(val bindin: ItemViewFeedsBinding) : RecyclerView.ViewHolder(bindin.root) {
    }

    private val differCallback = object : DiffUtil.ItemCallback<UserPost>() {
        override fun areItemsTheSame(oldItem: UserPost, newItem: UserPost): Boolean {
            return oldItem.postId == newItem.postId
        }

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

    val differ = AsyncListDiffer(this, differCallback)

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        var feedsItem = differ.currentList[position]
        holder.bindin.feedData = feedsItem;
        holder.bindin.executePendingBindings()
    }
    override fun getItemCount(): Int {
        return differ.currentList.size
    }
}

这个实现是否正确? 这是 ViewModel 还是适配器的问题? 请帮忙。提前致谢

【问题讨论】:

    标签: android kotlin android-recyclerview adapter android-diffutils


    【解决方案1】:
    1. 您可以区分创建活动的情况 第一次并从 savedInstanceState 中恢复。这是 通过覆盖 onSaveInstanceState 并检查参数来完成 onCreate。
    2. 您可以通过添加将活动锁定在一个方向 android:screenOrientation="portrait" (或 "landscape") 到 在您的清单中。
    3. 您可以告诉系统您打算处理屏幕更改 为自己指定 android:configChanges="orientation|screenSize" 在 标签。这样活动将不会被重新创建,但会收到一个 而是回调(您可以忽略它,因为它对您没有用处)。

    就个人而言,我会选择 (3)。当然,如果您可以将应用程序锁定到其中一个方向,您也可以使用 (2)。

    【讨论】:

    • 是的,我可以通过阻止景观来处理旋转问题。但是当我从另一个屏幕回来时,也会发生同样的情况。我需要解决这个问题。另外,我使用的是片段,而不是活动(单活动结构)
    • 这是因为 ViewModel 观察者在您返回片段时触发
    • viewModel.observeData().removeObservers(this); viewModel.observeData().observe(this, new Observer() {
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多