You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Hilt对两个自定义类实现字段注入?解决初始化报错

解决Dagger-Hilt注入LocationsListAdapter的依赖问题

问题核心:LocationsListAdapter是你手动实例化的类,并非Hilt管理的组件(如Activity/Fragment),因此Hilt不会自动处理它的字段注入,导致lateinit property categoryAvatar not initialized报错。以下是两种可行解决方案:

方案一:构造函数注入(推荐)

直接将CategoryAvatar作为适配器的构造参数,从Hilt管理的组件(如Activity/Fragment)中传入实例,这是最符合依赖注入设计原则的方式。

修改LocationsListAdapter.kt

class LocationsListAdapter(
    private val locationList: List<Result?>,
    private val categoryAvatar: CategoryAvatar // 新增构造参数
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    private val VIEW_TYPE_ITEM: Int = 0
    private val VIEW_TYPE_LOADING: Int = 1

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        // 直接使用categoryAvatar即可,无需lateinit字段
        if (viewType == VIEW_TYPE_ITEM){
            val view = LayoutInflater.from(parent.context).inflate(R.layout.locations_list_item , parent , false)
            return ItemViewHolder(view)
        } else {
            val view = LayoutInflater.from(parent.context).inflate(R.layout.item_loading , parent , false)
            return LoadingViewHolder(view)
        }
    }

    // 其他方法中直接调用categoryAvatar.getImageResourceId()即可
}

在创建适配器的组件中注入依赖

比如在Activity中:

@AndroidEntryPoint
class LocationListActivity : AppCompatActivity() {
    @Inject
    lateinit var categoryAvatar: CategoryAvatar

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_location_list)
        
        // 初始化数据源
        val locationList: List<Result?> = fetchLocations()
        // 创建适配器并传入依赖
        val adapter = LocationsListAdapter(locationList, categoryAvatar)
        binding.recyclerView.adapter = adapter
    }
}

方案二:使用EntryPoint注入(适配不想修改构造函数的场景)

通过EntryPoint从应用上下文获取Hilt管理的依赖,无需修改适配器构造函数。

1. 创建EntryPoint接口

@EntryPoint
@InstallIn(SingletonComponent::class)
interface CategoryAvatarEntryPoint {
    fun getCategoryAvatar(): CategoryAvatar
}

2. 在适配器中初始化依赖

class LocationsListAdapter(
    private val locationList: List<Result?>
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    private lateinit var categoryAvatar: CategoryAvatar

    private val VIEW_TYPE_ITEM: Int = 0
    private val VIEW_TYPE_LOADING: Int = 1

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        // 仅在首次初始化时获取依赖
        if (!::categoryAvatar.isInitialized) {
            val entryPoint = EntryPointAccessors.fromApplication(
                parent.context.applicationContext,
                CategoryAvatarEntryPoint::class.java
            )
            categoryAvatar = entryPoint.getCategoryAvatar()
        }
        
        if (viewType == VIEW_TYPE_ITEM){
            val view = LayoutInflater.from(parent.context).inflate(R.layout.locations_list_item , parent , false)
            return ItemViewHolder(view)
        } else {
            val view = LayoutInflater.from(parent.context).inflate(R.layout.item_loading , parent , false)
            return LoadingViewHolder(view)
        }
    }
}

注意事项

  • 确保你的Application类已添加@HiltAndroidApp注解,这是Hilt初始化的基础。
  • 使用方案一时,创建适配器的组件(Activity/Fragment)必须添加@AndroidEntryPoint注解,否则Hilt无法注入CategoryAvatar。

内容的提问来源于stack exchange,提问作者Amin soley

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 08:20:22