Bootstrap

Android开发实战班 -应用架构 之依赖注入(Hilt)

依赖注入(Dependency Injection, DI) 是一种设计模式,用于实现对象与其依赖项之间的解耦。在 Android 开发中,依赖注入可以帮助我们更高效地管理组件的生命周期、测试以及代码的可维护性。Hilt 是 Google 推出的一个基于 Dagger 的依赖注入库,专门为 Android 优化,简化了依赖注入的配置和使用。本章节将介绍依赖注入的基本概念、Hilt 的使用、Hilt 与 Jetpack 组件的集成以及实战案例。

13.1 依赖注入简介

  • 什么是依赖注入:

    • 依赖注入是一种设计模式,用于实现对象与其依赖项之间的解耦。
    • 通过依赖注入,类不再负责创建其依赖项,而是由外部注入依赖项。
  • 依赖注入的优势:

    • 解耦: 类与其依赖项解耦,提高代码的可维护性和可测试性。
    • 可测试性: 更容易编写单元测试,可以通过注入不同的依赖项来模拟不同的行为。
    • 可复用性: 依赖项可以在不同的类之间复用,减少代码重复。
    • 生命周期管理: 依赖项的生命周期可以由依赖注入框架管理,避免内存泄漏。

13.2 Hilt 简介

Hilt 是 Google 推出的一个基于 Dagger 的依赖注入库,专门为 Android 优化。Hilt 简化了 Dagger 的配置和使用,提供了与 Android Jetpack 组件的无缝集成。

  • Hilt 的优势:
    • 简化配置: Hilt 提供了预定义的组件和作用域,减少了 Dagger 的样板代码。
    • 与 Jetpack 集成: Hilt 与 Android Jetpack 组件(如 ViewModel, LiveData, Room 等)无缝集成。
    • 自动生成代码: Hilt 会自动生成 Dagger 组件和模块,减少手动配置的工作量。
    • 易于使用: Hilt 提供了简单的 API,易于上手和使用。

13.3 Hilt 的基本使用

13.3.1 添加 Hilt 依赖

build.gradle 文件中添加 Hilt 依赖:

// 项目级 build.gradle
dependencies {
    classpath "com.google.dagger:hilt-android-gradle-plugin:2.44"
}

// 应用级 build.gradle
plugins {
    id 'kotlin-kapt'
    id 'dagger.hilt.android.plugin'
}

android {
    ...
}

dependencies {
    implementation "com.google.dagger:hilt-android:2.44"
    kapt "com.google.dagger:hilt-compiler:2.44"
}
13.3.2 初始化 Hilt

Application 类上使用 @HiltAndroidApp 注解,初始化 Hilt:

@HiltAndroidApp
class MyApplication : Application()

AndroidManifest.xml 中注册 Application 类:

<application
    android:name=".MyApplication"
    ... >
    ...
</application>
13.3.3 使用 Hilt 注入依赖
  • 创建模块:

    • 使用 @Module@InstallIn 注解创建模块,定义依赖项。
    @Module
    @InstallIn(SingletonComponent::class)
    object AppModule {
    
        @Provides
        @Singleton
        fun provideUserRepository(): UserRepository {
            return UserRepository()
        }
    
        @Provides
        @Singleton
        fun provideApiService(): ApiService {
            return Retrofit.Builder()
                .baseUrl("https://api.example.com")
                .build()
                .create(ApiService::class.java)
        }
    }
    
  • 注入依赖:

    • 使用 @Inject 注解注入依赖。
    @AndroidEntryPoint
    class MyActivity : AppCompatActivity() {
    
        @Inject
        lateinit var userRepository: UserRepository
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            // 使用 userRepository
        }
    }
    
  • 注入 ViewModel:

    • 使用 @HiltViewModel 注解创建 ViewModel,并使用 @Inject 注入依赖。
    @HiltViewModel
    class MyViewModel @Inject constructor(
        private val userRepository: UserRepository
    ) : ViewModel() {
        // ViewModel 代码
    }
    
    @AndroidEntryPoint
    class MyActivity : AppCompatActivity() {
    
        private val viewModel: MyViewModel by viewModels()
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            // 使用 viewModel
        }
    }
    

13.4 Hilt 与 Jetpack 组件的集成

Hilt 与 Jetpack 组件(如 ViewModel, LiveData, Room 等)无缝集成,可以更方便地管理组件的生命周期和依赖关系。

  • ViewModel:

    • 使用 @HiltViewModel 注解创建 ViewModel,并注入依赖。
    @HiltViewModel
    class MyViewModel @Inject constructor(
        private val userRepository: UserRepository
    ) : ViewModel() {
        // ViewModel 代码
    }
    
  • LiveData:

    • Hilt 可以注入 ViewModel 所需的 LiveData。
    @HiltViewModel
    class MyViewModel @Inject constructor(
        private val userRepository: UserRepository
    ) : ViewModel() {
        val users: LiveData<List<User>> = userRepository.getUsers()
    }
    
  • Room:

    • Hilt 可以注入 Room 数据库和 DAO。
    @Module
    @InstallIn(SingletonComponent::class)
    object DatabaseModule {
    
        @Provides
        @Singleton
        fun provideDatabase(@ApplicationContext context: Context): AppDatabase {
            return Room.databaseBuilder(
                context,
                AppDatabase::class.java, "database-name"
            ).build()
        }
    
        @Provides
        fun provideUserDao(database: AppDatabase): UserDao {
            return database.userDao()
        }
    }
    

13.5 实战案例

  1. 案例一:使用 Hilt 实现用户列表应用

    • 创建一个 ViewModel,使用 Hilt 注入 UserRepository。
    • 在 Activity 中观察 ViewModel 的 LiveData,更新 RecyclerView。
    @HiltViewModel
    class UserViewModel @Inject constructor(
        private val userRepository: UserRepository
    ) : ViewModel() {
        val users: LiveData<List<User>> = userRepository.getUsers()
    }
    
    @AndroidEntryPoint
    class UserActivity : AppCompatActivity() {
    
        private val viewModel: UserViewModel by viewModels()
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_user)
    
            viewModel.users.observe(this) { users ->
                // 更新 UI
                val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
                recyclerView.adapter = UserAdapter(users)
            }
    
            viewModel.loadUsers()
        }
    }
    
  2. 案例二:使用 Hilt 实现图片浏览应用

    • 创建一个 ViewModel,使用 Hilt 注入 ApiService。
    • 在 Jetpack Compose Composable 中观察 ViewModel 的 Flow,更新 UI。
    @HiltViewModel
    class ImageViewModel @Inject constructor(
        private val apiService: ApiService
    ) : ViewModel() {
        val images: Flow<List<Image>> = apiService.fetchImages()
    }
    
    @Composable
    fun ImageScreen(viewModel: ImageViewModel) {
        val images by viewModel.images.collectAsState(initial = emptyList())
    
        LazyColumn {
            items(images) { image ->
                Image(
                    painter = painterResource(id = image.resId),
                    contentDescription = image.description
                )
            }
        }
    }
    

13.6 课后作业

  1. 任务一:使用 Hilt 实现用户列表应用

    • 创建一个 ViewModel,使用 Hilt 注入 UserRepository。
    • 在 Activity 中观察 ViewModel 的 LiveData,更新 RecyclerView。
  2. 任务二:使用 Hilt 实现图片浏览应用

    • 创建一个 ViewModel,使用 Hilt 注入 ApiService。
    • 在 Jetpack Compose Composable 中观察 ViewModel 的 Flow,更新 UI。
  3. 任务三:使用 Hilt 实现网络请求

    • 创建一个 ViewModel,使用 Hilt 注入 ApiService。
    • 在 Activity 中使用协程进行网络请求,并更新 UI。

通过本章节的学习,学员将能够掌握 Hilt 依赖注入的基本概念、使用方法以及与 Jetpack 组件的集成,并能够使用 Hilt 简化依赖管理,提高代码的可维护性和可测试性。

;