如何使用刀柄注射适配器

ccd*_*ccd 2 android android-recyclerview dagger-hilt

我有一个完整的recyclerView示例,现在我想使用hilt将此示例的ItemListAdapter注入到我的ItemListFragment中。但如果我还想要剑柄之道,似乎是做不到的。

class ItemListFragment : Fragment() {

    private val viewModel: ItemListViewModel by viewModels()
    private var adapter: ItemListAdapter? = null

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val binding = FragmentItemListBinding.inflate(inflater)
        binding.lifecycleOwner = this
        binding.viewModel = viewModel

        adapter =
            ItemListAdapter(
                ItemListOnClickListener { itemId ->
                    viewModel.onItemClicked(itemId)
                })
        binding.itemList.adapter = adapter

        return binding.root
    }
}

class ItemListAdapter(private val onClickListener: ItemListOnClickListener):
    ListAdapter<Item, ItemListAdapter.ViewHolder>(
        ItemListDiffCallback()
    ) {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(
            ListItemBinding.inflate(LayoutInflater.from(parent.context))
        )
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val item = getItem(position)
        holder.bind(item)
    }

    class ViewHolder constructor(private val binding: ListItemBinding) :
        RecyclerView.ViewHolder(binding.root) {
        fun bind(item: Item) {
            binding.item = item
            binding.executePendingBindings()
        }
    }
}

class ItemListDiffCallback : DiffUtil.ItemCallback<Item>() {
    override fun areItemsTheSame(oldItem: Item, newItem: Item): Boolean {
        return oldItem == newItem
    }

    override fun areContentsTheSame(oldItem: Item, newItem: Item): Boolean {
        return oldItem.id == newItem.id
    }
}

class ItemListOnClickListener(val clickListener: (itemID: String) -> Unit) {
    fun onClick(itemID: String) = clickListener(itemID)
}
Run Code Online (Sandbox Code Playgroud)

Ahm*_*ndy 7

这是你想要的吗?您可以检查一下这是否有效并满足您的需求。

注意:我希望您很好地设置了注释,以便在您的项目中设置并正常工作(例如:使用注释ItemListFragment片段@AndroidEntryPoint等...)

我遇到过这样的情况,我认为我应该通过适配器的 setter 方法提供回调,而不是在构造函数中提供回调。

对于ItemListAdapter,我们可以创建一个类型为 的属性ItemListOnClickListener,并提供setOnClickListenersetter方法。就是这样,现在您可以使用onClickListenerin ViewHolder(现在ItemListAdapter构造函数是无参数的,Hilt能够为您的情况提供绑定):

@Singleton
class ItemListAdapter @Inject constructor():
    ListAdapter<Item, ItemListAdapter.ViewHolder>(ItemListDiffCallback()) {
    
    private var onClickListener: ItemListOnClickListener? = null

    ...

    fun setOnClickListener(onClickListener: ItemListOnClickListener) {
        this.onClickListener = onClickListener;
    }

    inner class ViewHolder constructor(private val binding: ListItemBinding) :
            RecyclerView.ViewHolder(binding.root) {
        fun bind(item: Item) {
            binding.item = item
            binding.executePendingBindings()

            // Use `onClickListener` when binding `OnClickListener` callback
            binding.view.setOnClickListener(v -> onClickListener?.onClick(...))
        }
    }
}

Run Code Online (Sandbox Code Playgroud)

对于ItemListFragment,您不需要构建适配器,因为 Hilt 将能够为您提供一个。您所要做的就是通过setOnClickListener此适配器的方法提供一个侦听器:

@AndroidEntryPoint
class ItemListFragment: Fragment() {

    @Inject
    var adapter: ItemListAdapter? = null

    private val viewModel: ItemListViewModel by viewModels()

    override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View? {
        val binding = FragmentItemListBinding.inflate(inflater)

        ...

        adapter?.setOnClickListener(
                ItemListOnClickListener { 
                        itemId -> viewModel.onItemClicked(itemId) 
                }
        )

        binding.itemList.adapter = adapter

        return binding.root
    }
}
Run Code Online (Sandbox Code Playgroud)

  • `@Singleton` 对于适配器来说非常糟糕 (2认同)