具有多个项目类型的DataBoundListAdapter

时间:2018-07-16 15:34:49

标签: android android-recyclerview recycler-adapter android-architecture-components

我正在使用Android体系结构组件example中的DataBoundListAdapter。

我需要对其进行增强以支持多种商品类型。有人做过吗? 我的问题是如何在createBinding过程中找出项目类型,因为那里没有可用的项目位置,但是我需要它来获取项目类型,以便能够基于它来充气正确的布局。

@Override
    protected ChatMessageItemBinding createBinding(ViewGroup parent) {
        MyItemBinding binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), R.layout.my_item, parent,
                false, dataBindingComponent);


        return binding;
    }

2 个答案:

答案 0 :(得分:1)

查看DataBoundListAdapter的来源,我可以看到创建绑定只是来自onCreateViewHolder的调用,其中包含您需要的信息-viewType: Int

最简单的选择是覆盖方法在您自己的适配器中执行的操作,以传递所需的类型信息。

@Override
DataBoundViewHolder<V> onCreateViewHolder(ViewGroup parent, int viewType) {
    //Note: no call to super
    V binding = createBindingByType(parent, viewType) //this is a new method
    return DataBoundViewHolder(binding)
}

private ChatMessageItemBinding createBindingByType(ViewGroup parent, int viewType) {
    @LayoutRes int layout;
    switch(viewType) {
        case ...:
            layout = R.layout.my_item;
            break;
        ...
    }
    return DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), layout, parent, false, dataBindingComponent);
}

@Override
protected ChatMessageItemBinding createBinding(ViewGroup parent) {
    throw new RuntimeException("This method should not be called with MyAdapter");
}

答案 1 :(得分:0)

重用GithubBrowserSample的相同类,我认为其中一种方法可能是忽略DataBoundListAdapter并像这样直接实现ListAdapter

/**
 * A RecyclerView adapter for [Repo] class.
 */
class RepoListAdapterFor2Types(
        private val dataBindingComponent: DataBindingComponent,
        appExecutors: AppExecutors,
        private val showFullName: Boolean,
        private val repoClickCallback: ((Repo, viewType: Int) -> Unit)?
) : ListAdapter<Repo, DataBoundViewHolder<RepoItemBinding>>(
        AsyncDifferConfig.Builder<Repo>(
            object : DiffUtil.ItemCallback<Repo>() {
                override fun areItemsTheSame(oldItem: Repo, newItem: Repo): Boolean {
                    return oldItem.owner == newItem.owner
                            && oldItem.name == newItem.name
                }

                override fun areContentsTheSame(oldItem: Repo, newItem: Repo): Boolean {
                    return oldItem.description == newItem.description
                            && oldItem.stars == newItem.stars
                }
        })
        .setBackgroundThreadExecutor(appExecutors.diskIO())
        .build()
) {

    override fun getItemViewType(position: Int): Int {
        val repo = getItem(position)
        //this is just for the example
        return when (repo.id) {
            1 -> 1
            else -> 2
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DataBoundViewHolder<RepoItemBinding> {
        val binding = createBinding(parent, viewType)
        return DataBoundViewHolder(binding)
    }

    override fun onBindViewHolder(holder: DataBoundViewHolder<RepoItemBinding>, position: Int) {
        holder.binding.repo = getItem(position)
        holder.binding.executePendingBindings()
    }

    private fun createBinding(parent: ViewGroup, viewType: Int): RepoItemBinding {
        @LayoutRes val layout = when (viewType) {
            1 -> R.layout.repo_item_type_1
            else -> R.layout.repo_item_type_2
        }
        val binding = DataBindingUtil.inflate<RepoItemBinding>(
            LayoutInflater.from(parent.context),
            layout,
            parent,
            false,
            dataBindingComponent
        )
        binding.showFullName = showFullName
        binding.root.setOnClickListener {
            binding.repo?.let {
                repoClickCallback?.invoke(it, viewType)
            }
        }
        return binding
    }
}

如果您需要使用完全不同的物品,请使用其他物品。您将无法使用2个diff回调,因此您可能应该编写自己的ListAdapter实现