Android分页3:可以从PagingData<T>获取itemcount吗?

And*_*rew 10 paging android mvvm android-paging

我怎样才能获得我PagingData<Product>持有的当前物品数量?我找到的唯一解决方案是调用,shopListAdapter.itemCount但这总是返回 0。

我想做的是:获取我的 PagingAdapter 当前显示的项目数量,将该值提交给我的 shopViewModel,然后在另一个片段(DialogFragment)中使用该值。PagingData<Product>或者:从我的视图模型内部获取项目数量

这是我目前的方法

主片段

@AndroidEntryPoint
class ShopFragment : Fragment(R.layout.fragment_shop), ShopAdapter.OnItemClickListener {
    private val shopViewModel: ShopViewModel by navGraphViewModels(R.id.nav_shop) { defaultViewModelProviderFactory }
    private var _shopBinding: FragmentShopBinding? = null
    private val shopBinding: FragmentShopBinding get() = _shopBinding!!
    @Inject lateinit var shopListAdapter: ShopAdapter

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _shopBinding = FragmentShopBinding.inflate(inflater, container, false)
        return shopBinding.root
    }

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

    private fun collectShopList(){
        shopViewModel.shopPagingData.observe(viewLifecycleOwner)  {
            shopListAdapter.submitData(viewLifecycleOwner.lifecycle, it)
            shopViewModel.setItemAmount(shopListAdapter.itemCount)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

对话框片段

@AndroidEntryPoint
class ShopFilterFragment : DialogFragment() {
    private val shopViewModel: ShopViewModel by navGraphViewModels(R.id.nav_shop) { defaultViewModelProviderFactory }

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

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        shopViewModel.itemAmount.observe(viewLifecycleOwner) {
            toast(it.toString()) <-- Always displays 0
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

视图模型

class ShopViewModel @ViewModelInject constructor(
    private val shopRepository: ShopRepository
) : ViewModel() {
    private val _itemAmount = MutableLiveData<Int>()
    val itemAmount: LiveData<Int> get() = _itemAmount

    private val query = MutableLiveData(QueryHolder(null, null, null))

    val shopPagingData = query.switchMap { query -> shopRepository.search(query).cachedIn(viewModelScope) }

    fun search(newQuery: QueryHolder) {
        query.value = newQuery
    }

    fun setItemAmount(amount: Int) {
        _itemAmount.value = amount
    }
}
Run Code Online (Sandbox Code Playgroud)

dla*_*lam 15

adapter.itemCount是正确的方法,但请注意,它有可能与适配器收到的内容竞争(页面将加载,然后通知适配器 - 如果您.itemCount在这些步骤之间调用,它将返回错误的数字)。

要等待适配器呈现页面,最简单的方法是使用loadStateListener/ loadStateFlow,因为LoadState保证更新与适配器事件同步。

shopListAdapter.addLoadStateListener { combinedLoadStates ->
  // If you don't want to call all the time, you
  // can filter on changes in combinedLoadStates
  shopViewModel.setItemAmount(shopListAdapter.itemCount)
}
Run Code Online (Sandbox Code Playgroud)

如果发生泄漏,请不要忘记取消注册。

或者,您可以使用基于流程的方法:

.. onViewCreated(..) {
  viewLifecycleOwner.lifecycleScope.launch {
    shopListAdapter.loadStateFlow.collect { combinedLoadStates ->
      // If you don't want to call all the time, you
      // can filter on changes in combinedLoadStates
      shopViewModel.setItemAmount(shopListAdapter.itemCount)
    }
  }
}
Run Code Online (Sandbox Code Playgroud)