我正在尝试为嵌套列表实现一个类似的系统。我使用 AdapterDelegates、MVVM、StateFlow。 屏幕看起来像这样: https://i.imgur.com/VqqM9fP.png
数据来自api,在视图中Models被扔进StateFlow:
class HomeViewModel @Inject constructor(private val repository: Repository,) : ViewModel() {
private val _data = MutableStateFlow<List<HomeScreen>>(emptyList())
val data = _data.asStateFlow()
init {createHomeScreen()}
private fun createHomeScreen() {
viewModelScope.launch(Dispatchers.IO) {
_data.value = repository.getItems()
}
}
...
}
进一步在片段中,整个东西都放入适配器中:
class HomeFragment : Fragment {
private val adapter by lazy {HomeAdapter { clickableView, item ->onItemClick(clickableView, item)}}
viewLifecycleOwner.lifecycleScope.launch {
viewModel.data.collect{ data ->
adapter.items = data
}
}
private fun onItemClick(clickableView: ClickableView, item: Item) {
viewModel.onItemClick(clickableView, item)
}
}
外部适配器:
class HomeAdapter(onItemClick: (ClickableView, Item) -> Unit) :
AsyncListDifferDelegationAdapter<HomeScreen>(HomeScreenDiffUtil()) {
init {
delegatesManager
.addDelegate(horizontalGridDelegate(onItemClick))
}
}
它的代表:
fun horizontalGridDelegate(onItemClick: (ClickableView, Item) -> Unit) =
adapterDelegateViewBinding<HorizontalGrid, HomeScreen, ItemContainerViewHolderBinding>({ inflater, root ->
ItemContainerViewHolderBinding.inflate(inflater, root, false)
}) {
bind {
binding.bind(item){clickableView, item ->
clickableView.listPosition = bindingAdapterPosition
onItemClick(clickableView, item) }
}
}
fun ItemContainerViewHolderBinding.bind(
item: HomeScreen,
onItemClick: (ClickableView, Item) -> Unit
) {
val dogAdapter = OneListItemAdapter(onItemClick)
recyclerView.adapter = dogAdapter
dogAdapter.items = item.list
...
)
}
内部适配器及其代表:
class OneListItemAdapter(onItemClick: (ClickableView, Item) -> Unit) :
AsyncListDifferDelegationAdapter<Item>(ItemDiffUtil()) {
init {
delegatesManager
.addDelegate(dogsDelegate(onItemClick))
}
}
fun dogsDelegate(onItemClick: (ClickableView, Item) -> Unit) =
adapterDelegateViewBinding<Dog, Item, DogViewHolderBinding>({ inflater, root ->
DogViewHolderBinding.inflate(inflater, root, false)
}) {
binding.btnFavorite.setOnClickListener {
/**need this click*/
ClickableView.FAVORITE.itemPosition = bindingAdapterPosition
onItemClick(ClickableView.FAVORITE, item)
}
bind {
binding.btnFavorite.isSelected = item.isFavorite
}
}
问题本质:
您不能只将选择器设置为在单击时触发,因为对服务器的请求可能无法通过。因此,您需要以某种方式在流程中胜任地发出它。到目前为止,我已经尝试这样做:
... ViewModel() {
private fun addToFavorites(item: Dog, itemPosition: Int, listPosition: Int) {
viewModelScope.launch(Dispatchers.IO) {
val newData = _data.value.toMutableList()
val newList = newData[listPosition].list.toMutableList() as MutableList<Dog>
newList[itemPosition] =
newList[itemPosition].copy(isFavorite = !newList[itemPosition].isFavorite)
newData[listPosition] = (newData[listPosition] as HorizontalGrid).copy(list = newList)
_data.value = newData
}
}
}
但是通过这个实现,我也更新了整个内部回收器。 也许来自 DiffUtil 的有效负载会帮助我。但是我没有足够的知识,包括 Kotlin,无法实现它们。或者也许还有其他方法?我已经浏览了很多关于委托的信息,但我还没有在任何地方遇到对象重绘。我知道在这种情况下你完全可以不用委托,但目标是使用这个特定的库。提前谢谢你