PagedListAdapter.submitList()在更新现有项目时表现得很奇怪

bla*_*ara 12 android android-architecture-components android-paging androidx

这个主题的小故事:应用程序只是在确认后用对话框更新点击行的值.在房间数据库上使用分页方案.

添加或删除项目时,将获取最新数据集并将其传递给submitList方法,然后可以看到所有更改并运行良好.

问题从那里开始,如果现有项目更新,则再次正确获取最新数据集并传递给submitList,但这次似乎没有变化.

当我调试DIFF_CALLBACK并抓住我的项目时areItemsTheSame,newHistoryoldHistory值是一样的!(怎么样!)

submitList方法中可能有任何错误?

  • 房间v.:2.1.0-alpha02
  • Paging v.:2.1.0-beta01

初始化后,observe从房间中提取列表并传递给mHistoryAdapter.submitList(it).然后,如果我更新一个项目,观察再次被触发(我在param中看到更新的值it)并传递给submitList.

不幸的是,适配器不会改变......

    mResolvedAddressViewModel = ViewModelProviders.of(this).get(ResolvedAddressViewModel::class.java)
    mResolvedAddressViewModel.getAddresses(false).observe(this, Observer {
        mHistoryAdapter.submitList(it)
    })
Run Code Online (Sandbox Code Playgroud)

所有部件

模型

@Parcelize
@Entity
data class ResolvedAddress(
    @PrimaryKey var id: String = UUID.randomUUID().toString(),
    var requestedLat: Double = 0.0,
    var requestedLon: Double = 0.0,
    var requestedAddress: String = "",
    var lat: Double,
    var lon: Double,
    var address: String,
    var country: String,
    var countryCode: String,
    var city: String,
    var alias: String? = null,
    var favorite: Boolean = false,
    var provider: String? = null,
    var lastUseDate: Long = 0L) : Parcelable
Run Code Online (Sandbox Code Playgroud)

适配器

class HistoryAdapter(var context: Context)
: PagedListAdapter<ResolvedAddress, HistoryItemHolder>(DIFF_CALLBACK) {

    companion object {
        private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<ResolvedAddress>() {
            override fun areItemsTheSame(
                oldHistory: ResolvedAddress, newHistory: ResolvedAddress): Boolean {
                return oldHistory.id == newHistory.id
            }

            override fun areContentsTheSame(
                oldHistory: ResolvedAddress, newHistory: ResolvedAddress): Boolean {
                return oldHistory == newHistory
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

分段

class HistoryFragment : Fragment() {
    private lateinit var mHistoryAdapter: HistoryAdapter
    private lateinit var mResolvedAddressViewModel: ResolvedAddressViewModel

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, 
        savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_history, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        recyclerViewHistory.setHasFixedSize(true)
        recyclerViewHistory.layoutManager = LinearLayoutManager(activity)
        recyclerViewHistory.itemAnimator = DefaultItemAnimator()

        mHistoryAdapter = HistoryAdapter(context!!)
        recyclerViewHistory.adapter = mHistoryAdapter

        mResolvedAddressViewModel = ViewModelProviders.of(this)
        .get(ResolvedAddressViewModel::class.java)

        mResolvedAddressViewModel.getAddresses(false).observe(this, Observer {
            mHistoryAdapter.submitList(it)
        })
    }
}
Run Code Online (Sandbox Code Playgroud)

Fel*_*riz 6

该问题中缺少几件事,可能有助于提供更详细的答案。

例如 你RecyclerView.Adapter长什么样 它会扩展PagedListAdapter吗?

您的模型课程是什么样的?它是Kotlin数据类吗?


为了提供答案,让我们假设那些未知数是我们所期望的。

如果我理解这个问题,似乎您只是updating一个项目,而没有删除或添加任何项目。因此,DiffUtil.ItemCallbackareItemsTheSame将始终返回true,因为旧列表和新列表的大小均未修改。意思是,如果您更新了一项,则可能已更新了其内容,而未将其从列表中删除。

因此,areItemsTheSame将返回true,因为它们的id仍然相同。

areContentsTheSame由于更新了项目的内容,因此第二种方法更有可能返回false。

如果您的模型类ResolvedAddress是Kotlin数据类,则areContentsTheSame在比较从旧列表和新列表更新的项目时,该方法应返回false。这将onBindViewHolder在此时触发适配器中的方法,以便您将该项目与更新的数据重新绑定。

如果该模型不是Kotlin data class,则必须确保该类实现该compareTo方法。如果不是,则将对象的内存地址与对象的实际内容进行比较。在这种情况下,该方法areContentsTheSame将始终返回true,因为对象的内存地址未更改。

这些是一些调试技巧,因为如果没有更多有关如何实现代码的知识,很难提供更清晰的答案。

  • 你解决了吗?有同样的问题。 (2认同)