Kotlin中如何用Dagger2实现Adapter的依赖注入?
首先得明确:Adapter不像Activity/Fragment是由Android系统实例化并能被Dagger自动处理的组件,所以得手动处理依赖注入的时机,下面给你两种常用的解决方案:
方案一:构造函数传参(推荐,更符合依赖注入思想)
这种方式不需要修改你的Dagger Component,核心是把需要的依赖通过Adapter的构造函数传入,让Adapter的依赖完全由外部提供,既清晰又方便测试。
修改Adapter的构造函数
在ExpandableDraggableSwipeableAdapter里,把AccountType作为构造参数添加进去:class ExpandableDraggableSwipeableAdapter( private val accountType: AccountType, // 保留你原来需要的其他参数,比如数据源等 ) : BaseExpandableListAdapter() { // ... 你的其他Adapter代码 // 子视图点击时直接用传入的accountType做检查 override fun onChildClick( parent: ExpandableListView?, v: View?, groupPosition: Int, childPosition: Int, id: Long ): Boolean { if (accountType.isAdmin()) { // 执行管理员专属操作 } else { // 普通用户操作逻辑 } return true } }在Fragment/Activity中创建Adapter时传入依赖
既然你的Fragment/Activity已经能正常注入依赖,直接从这里拿到AccountType传给Adapter就行:class YourHostFragment : Fragment() { // 先在Fragment中注入AccountType @Inject lateinit var accountType: AccountType override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { // ... 初始化视图逻辑 val adapter = ExpandableDraggableSwipeableAdapter(accountType, yourDataSource) expandableListView.setAdapter(adapter) return view } }
方案二:通过Dagger Component手动注入(适合复杂场景)
如果你坚持要用Dagger的inject方法来注入,关键是要保证在Adapter使用依赖之前完成注入操作,不能等到Adapter的生命周期方法里才处理。
确认Component的inject方法定义正确
你现有的ActivityComponent定义没问题,继续保留:interface ActivityComponent : BaseComponent { fun inject(expDragSwipeAdapter: ExpandableDraggableSwipeableAdapter) }在Adapter中添加待注入的成员变量
用@Inject标注需要注入的变量,注意不要设为private(或者用@JvmField标注):class ExpandableDraggableSwipeableAdapter : BaseExpandableListAdapter() { @Inject lateinit var accountType: AccountType // ... 其他Adapter代码 override fun onChildClick(...) : Boolean { // 这里就能正常使用accountType了 return true } }在Fragment/Activity中创建Adapter后立即调用注入
必须在Adapter绑定到ListView之前,调用Component的inject方法完成注入:class YourHostFragment : Fragment() { // 注入ActivityComponent(或者从宿主Activity中获取) @Inject lateinit var activityComponent: ActivityComponent override fun onCreateView(...) : View? { // ... 初始化视图 val adapter = ExpandableDraggableSwipeableAdapter() // 关键:创建Adapter后立刻注入! activityComponent.inject(adapter) expandableListView.setAdapter(adapter) return view } }
为什么之前注入对象为空?
你之前遇到的问题,大概率是因为在Adapter的onCreate方法里才尝试注入——这时候Adapter已经被系统初始化并绑定到视图了,而且Dagger的inject方法根本没被调用(或者调用时机太晚),导致accountType一直处于未初始化状态。记住:Dagger不会自动注入非Android系统组件,必须手动调用inject方法,且要在使用依赖之前完成。
总的来说,方案一更推荐,它让Adapter的依赖关系更透明,单元测试时还能轻松传入Mock的AccountType。
内容的提问来源于stack exchange,提问作者Rupesh




