[英]How to inject adapter with 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)
}
這是你想要的嗎? 你能檢查一下這是否有效並滿足你的需要嗎?
注意:我希望您能很好地設置注釋,以便在您的項目中正確設置和工作刀柄(例如:使用@AndroidEntryPoint
注釋ItemListFragment
片段等...)
我遇到過這樣的情況,我認為與其在構造函數中提供回調,不如通過適配器的 setter 方法提供它。
對於ItemListAdapter
,我們可以創建一個ItemListOnClickListener
類型的屬性,並提供setOnClickListener
setter 方法。 就是這樣,現在您可以在ViewHolder
onClickListener
現在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(...))
}
}
}
對於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
}
}
2021 年 2 月答復
這是最簡單的答案。
在模塊 class 中
@Module
@InstallIn(SingletonComponent::class)
class AppModule {
@Provides
@Singleton
fun provideAdapter(): MyAdapter = MyAdapter()
}
在適配器 class
private var onItemClickListener: ((RestaurantX) -> Unit)? = null
fun setOnItemClickListener(listener: (RestaurantX) -> Unit) {
onItemClickListener = listener
}
然后把這一行放在view.setOnClckListener
里面
onItemClickListener?.let {
it(restaurantX)
}
在活動/片段中
@Inject
lateinit var myAdapter: MyAdapter
然后在一個方法里面
myAdapter.setOnItemClickListener {it->
//do whatever you like
}
如果您仍然感到困惑,這里是完整的源代碼
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.