通过SunFlower学习Hilt基本使用

文章目录

根据理解,使用SunFlower实例演示hilt基本使用。

添加hilt配置

  • 添加hilt gradle插件

    buildscript {
    dependencies {
    classpath "com.google.dagger:hilt-android-gradle-plugin:$hiltVersion"
    }
    }

  • 配置module使用插件进行注解处理

    apply plugin: 'kotlin-kapt'
    apply plugin: 'dagger.hilt.android.plugin'

  • 配置hilt依赖库版本

    dependencies {
    kapt "com.google.dagger:hilt-android-compiler:rootProject.hiltVersion" implementation "com.google.dagger:hilt-android:rootProject.hiltVersion"

  • App启用hilt

    @HiltAndroidApp
    class MainApplication : Application()

数据库自动注入

常规kotlin 规范创建AppDatabase、表、查询封装Dao

  • 创建数据库

    @Database(entities = [GardenPlanting::class, Plant::class], version = 1, exportSchema = false)
    @TypeConverters(Converters::class)
    abstract class AppDatabase : RoomDatabase() {
    abstract fun gardenPlantingDao(): GardenPlantingDao
    abstract fun plantDao(): PlantDao

    复制代码
      companion object {
    
          // For Singleton instantiation
          @Volatile private var instance: AppDatabase? = null
    
          fun getInstance(context: Context): AppDatabase {
              return instance ?: synchronized(this) {
                  instance ?: buildDatabase(context).also { instance = it }
              }
          }
    
          // Create and pre-populate the database. See this article for more details:
          // https://medium.com/google-developers/7-pro-tips-for-room-fbadea4bfbd1#4785
          private fun buildDatabase(context: Context): AppDatabase {
              return Room.databaseBuilder(context, AppDatabase::class.java, DATABASE_NAME)
                  .addCallback(
                      object : RoomDatabase.Callback() {
                          override fun onCreate(db: SupportSQLiteDatabase) {
                              super.onCreate(db)
                              val request = OneTimeWorkRequestBuilder<SeedDatabaseWorker>().build()
                              WorkManager.getInstance(context).enqueue(request)
                          }
                      }
                  )
                  .build()
          }
      }

    }

  • 创建实体类

    @Entity(tableName = "plants")
    data class Plant(
    @PrimaryKey @ColumnInfo(name = "id") val plantId: String,
    val name: String,
    val description: String,
    val growZoneNumber: Int,
    val wateringInterval: Int = 7, // how often the plant should be watered, in days
    val imageUrl: String = ""
    ) {

    复制代码
      /**
       * Determines if the plant should be watered.  Returns true if [since]'s date > date of last
       * watering + watering Interval; false otherwise.
       */
      fun shouldBeWatered(since: Calendar, lastWateringDate: Calendar) =
          since > lastWateringDate.apply { add(DAY_OF_YEAR, wateringInterval) }
    
      override fun toString() = name

    }

  • 创建查询Dao

    @Dao
    interface PlantDao {
    @Query("SELECT * FROM plants ORDER BY name")
    fun getPlants(): Flow<List<Plant>>

    复制代码
      @Query("SELECT * FROM plants WHERE growZoneNumber = :growZoneNumber ORDER BY name")
      fun getPlantsWithGrowZoneNumber(growZoneNumber: Int): Flow<List<Plant>>
    
      @Query("SELECT * FROM plants WHERE id = :plantId")
      fun getPlant(plantId: String): Flow<Plant>
    
      @Insert(onConflict = OnConflictStrategy.REPLACE)
      suspend fun insertAll(plants: List<Plant>)

    }

创建DatabaseModule,向外提供数据库访问方法

数据库、PlantDao等不能直接添加@Inject注解构造函数,需要创建单独的module进行对外提供。

复制代码
@InstallIn(SingletonComponent::class)
@Module
class DatabaseModule {

    @Singleton
    @Provides
    fun provideAppDatabase(@ApplicationContext context: Context): AppDatabase {
        return AppDatabase.getInstance(context)
    }

    @Provides
    fun providePlantDao(appDatabase: AppDatabase): PlantDao {
        return appDatabase.plantDao()
    }

@InstallIn和@Provider上Scope关系

@InstallIn指定module要注入的生成的component,@Provider函数可以添加Scoped限定符,但是必须与@InstallIn作用域一致。

@Provider函数添加Scoped限定符后,在component范围内仅仅创建一个实例。

Android 类 生成的组件 作用域
Application SingletonComponent @Singleton
Activity ActivityRetainedComponent @ActivityRetainedScoped
ViewModel ViewModelComponent @ViewModelScoped
Activity ActivityComponent @ActivityScoped
Fragment FragmentComponent @FragmentScoped

将模块安装到组件后,其绑定就可以用作该组件中其他绑定的依赖项,也可以用作组件层次结构中该组件下的任何子组件中绑定的依赖项。

这个函数直接向容器提供了AppDatabase、PlantDao对象。

PlantRepository 使用 PlantDao

复制代码
@Singleton
class PlantRepository @Inject constructor(private val plantDao: PlantDao) {

    fun getPlants() = plantDao.getPlants()

    fun getPlant(plantId: String) = plantDao.getPlant(plantId)

    fun getPlantsWithGrowZoneNumber(growZoneNumber: Int) =
        plantDao.getPlantsWithGrowZoneNumber(growZoneNumber)
}

@Singleton 这个和dagger2 @Module Provider方法限定符效果一样,标志在注入Component范围内单例。

@Inject 标志当component需要注入PlantRepository对象时,可以直接调用该函数进行获取。

@Inject constructor 参数plantDao,标志component使用PlantRepository对象时,需要提供的对象。

ViewModel使用PlantRepository

@HiltViewModel标志ViewModel自动进行构造函数注入

且必须存在@Inject修饰的构造函数

复制代码
@HiltViewModel
class PlantDetailViewModel @Inject constructor(
    savedStateHandle: SavedStateHandle,
    plantRepository: PlantRepository,
    private val gardenPlantingRepository: GardenPlantingRepository,
) : ViewModel() {

    val plantId: String = savedStateHandle.get<String>(PLANT_ID_SAVED_STATE_KEY)!!

Fragment声明需要进行注入

@AndroidEntryPoint标志注入入口点

@AndroidEntryPoint 标志,当前Activity、Fragment需要进行hilt注入。
注:Fragment添加后,其所在的Activity同样必须添加

复制代码
@AndroidEntryPoint
class GardenActivity : AppCompatActivity() {



@AndroidEntryPoint
class PlantDetailFragment : Fragment() {

    private val plantDetailViewModel: PlantDetailViewModel by viewModels()

sunflower 仓库地址

gd771747384/sunflower

相关推荐
西岸行者9 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意9 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码9 天前
嵌入式学习路线
学习
毛小茛9 天前
计算机系统概论——校验码
学习
babe小鑫9 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms9 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下9 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。9 天前
2026.2.25监控学习
学习
im_AMBER9 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode
CodeJourney_J9 天前
从“Hello World“ 开始 C++
c语言·c++·学习