Android Hilt 入门教程_传统写法和Hilt写法的比较

一 Hilt为什么是解耦利器 和测试友好助手

Hilt 之所以被称为 "解耦利器" 和 "测试友好助手" ,是因为它能让 类之间的依赖关系更加松散 ,并且 支持在测试时轻松替换依赖。

我们从 解耦(Decoupling) 和 测试友好(Testability) 两个方面分别解释,并提供示例代码来说明。


🎯 1. Hilt 是如何解耦代码的?

✅ 传统写法(紧耦合,难以扩展)

kotlin 复制代码
class MyRepository {
    private val apiService = ApiService()  // 直接创建实例(强依赖)
    
    fun fetchData(): String {
        return apiService.getData()
    }
}

❌ 问题

  • MyRepository 直接依赖 ApiService,导致:
    1. 难以替换 (如果要改用 FakeApiService 进行测试,就得修改 MyRepository 代码)
    2. 扩展性差 (如果 ApiService 需要不同的实现方式,就得改 MyRepository)
    3. 不适合单元测试(不能注入模拟数据)

✅ 使用 Hilt 进行解耦

kotlin 复制代码
class MyRepository @Inject constructor(private val apiService: ApiService) {
    fun fetchData(): String {
        return apiService.getData()
    }
}

Hilt 提供的 ApiService 实例

kotlin 复制代码
@Module
@InstallIn(SingletonComponent::class)
object AppModule {

    @Provides
    @Singleton
    fun provideApiService(): ApiService {
        return RealApiService()
    }
}

✅ 解耦优势

  1. MyRepository 只依赖 ApiService 抽象 ,不关心 ApiService 具体是怎么来的
  2. 可以轻松替换 ApiService (比如切换到 FakeApiService 进行测试)
  3. 代码更清晰 ,职责更明确(Hilt 负责管理依赖,不再手动 new)

🔬 2. Hilt 是如何让测试变得更简单的?

Hilt 允许我们在测试时 替换真实依赖,避免复杂的网络请求、数据库操作等,从而更快、更稳定地测试业务逻辑。

✅ 1. 不使用 Hilt,测试困难

kotlin 复制代码
@Test
fun testFetchData() {
    val repo = MyRepository(ApiService())  // 依赖真实的 ApiService
    val result = repo.fetchData()
    assertEquals("Expected Data", result)  // 可能失败,因为是真实数据
}

❌ 问题

  • MyRepository 无法使用 Mock 依赖
  • 每次测试都会访问真实 API(影响速度、可能失败)
  • 代码可测试性 非常低

✅ 2. 使用 Hilt 轻松替换依赖

🛠️ 在测试中提供 FakeApiService

kotlin 复制代码
@HiltAndroidTest
@UninstallModules(AppModule::class) // 先卸载正式模块
class MyRepositoryTest {

    @Module
    @InstallIn(SingletonComponent::class)
    object TestModule {
        @Provides
        fun provideFakeApiService(): ApiService {
            return object : ApiService {
                override fun getData(): String {
                    return "Fake Data"
                }
            }
        }
    }

    @Inject
    lateinit var repository: MyRepository

    @get:Rule
    var hiltRule = HiltAndroidRule(this)

    @Before
    fun setup() {
        hiltRule.inject()  // 让 Hilt 注入测试依赖
    }

    @Test
    fun testFetchData() {
        val result = repository.fetchData()
        assertEquals("Fake Data", result)  // 100% 可预测的测试结果
    }
}

✅ 测试优势

  1. 自动替换真实依赖(不再访问网络或数据库)
  2. 测试速度更快(不依赖外部服务)
  3. Mock 数据可预测(不会受外部 API 变动影响)

📌 总结

特点 传统依赖方式 使用 Hilt
代码解耦 直接 new 对象,强依赖具体实现 依赖抽象,Hilt 负责提供实现
可扩展性 变更时需要修改多个类 只需修改 @Module 提供的依赖
测试友好 依赖真实 API,难以 Mock 轻松替换 Mock 依赖,提高测试效率
代码可维护性 依赖关系混乱,难以管理 依赖关系清晰,代码模块化

🚀 一句话总结

Hilt = 解耦利器 + 测试友好助手 ,让的代码 更模块化、更易测试、更易维护!


九 Hilt为什么是对象工厂 和 生命周期管家 ?

Hilt 之所以是 对象工厂 和 生命周期管家 ,是因为它能够 自动创建并管理依赖对象 ,并且可以 自动适配依赖对象的生命周期,避免手动管理带来的复杂性和潜在的内存泄漏。


🎭 1. Hilt 是对象工厂(自动创建并管理依赖对象)

在没有 Hilt 的情况下,我们通常需要手动创建对象:

kotlin 复制代码
class MyRepository {
    private val apiService = ApiService()  // 直接创建实例
}

❌ 问题

  • MyRepository 依赖 ApiService,必须手动 new,不灵活
  • 如果 ApiService 还依赖 Retrofit,就需要 new 多个对象,依赖链复杂

✅ Hilt 作为对象工厂

Hilt 通过 @Module + @Provides 或 @Inject 构造注入 自动创建对象:

kotlin 复制代码
class MyRepository @Inject constructor(private val apiService: ApiService) { }

Hilt 自动提供 ApiService 实例

kotlin 复制代码
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
    @Provides
    @Singleton
    fun provideApiService(): ApiService {
        return Retrofit.Builder()
            .baseUrl("https://api.example.com/")
            .addConverterFactory(GsonConverterFactory.create())
            .build()
            .create(ApiService::class.java)
    }
}

🎯 关键点

  1. Hilt 自动创建 ApiService,并将其注入到 MyRepository
  2. 我们不需要手动 new,Hilt 充当工厂,自动提供对象
  3. 如果 ApiService 还有依赖(如 Retrofit),Hilt 也会自动解析并注入

🕰️ 2. Hilt 是生命周期管家(自动管理对象生命周期)

在 Android 开发中,不同作用域的对象需要不同的生命周期,比如:

  • Application 级别的单例(整个应用共享)
  • Activity 级别的实例(Activity 销毁时自动清理)
  • Fragment 级别的实例(Fragment 关闭时释放)

❌ 传统方式:手动管理生命周期

kotlin 复制代码
class MainActivity : AppCompatActivity() {
    private val repository = MyRepository(ApiService()) // 手动创建,难以管理
}

❌ 问题

  • 全局变量会导致内存泄漏
  • Activity 重建(如旋转屏幕)后,数据可能丢失
  • 手动管理生命周期非常繁琐

✅ Hilt 自动管理生命周期

Hilt 通过作用域(@InstallIn(Component::class))自动匹配生命周期:

🎯 Application 作用域(全局单例)

kotlin 复制代码
@InstallIn(SingletonComponent::class) // Application 级别
@Module
object AppModule {
    @Provides
    @Singleton
    fun provideMyRepository(apiService: ApiService): MyRepository {
        return MyRepository(apiService)
    }
}
  • 全局单例 :SingletonComponent 作用域下的对象,整个应用生命周期内存储
  • 避免重复创建 :所有使用 MyRepository 的地方,都共享同一个实例

🎯 Activity 作用域(Activity 级别)

kotlin 复制代码
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    private val viewModel: MainViewModel by viewModels() // Hilt 自动管理生命周期
}
@HiltViewModel
class MainViewModel @Inject constructor(
    private val repository: MyRepository
) : ViewModel()
  • @HiltViewModel 绑定 ViewModel 生命周期 ,当 Activity 关闭时,ViewModel 也会自动销毁
  • MyRepository 仍然是 Singleton 作用域的,所以 MainViewModel 依赖它,但不会重复创建

🎯 Fragment 作用域

如果 Fragment 需要自己的 ViewModel:

kotlin 复制代码
@AndroidEntryPoint
class MyFragment : Fragment() {
    private val viewModel: MyViewModel by viewModels()
}
@HiltViewModel
class MyViewModel @Inject constructor(
    private val repository: MyRepository
) : ViewModel()
  • MyViewModel 与 Fragment 绑定,Fragment 销毁时自动释放
  • 不会因为 Activity 变化导致数据丢失

📌 结论

特性 传统方式 使用 Hilt
对象管理 手动 new,难以管理 Hilt 自动创建并管理依赖
依赖关系 需要手动传递依赖 Hilt 通过 @Inject 自动注入
生命周期管理 需要手动释放对象,避免内存泄漏 Hilt 自动匹配对象生命周期
测试支持 需要大量 Mock Hilt 允许轻松替换依赖

💡 总结

Hilt 作为 "对象工厂",自动创建并管理依赖对象

Hilt 作为 "生命周期管家",自动管理作用域,防止内存泄漏

这样,我们就能更专注于业务逻辑,而不用操心依赖创建和生命周期管理!

相关推荐
三少爷的鞋1 小时前
AI 时代,我们都将成为通才型开发者:只懂 Android,已经不够了
android
Dovis(誓平步青云)5 小时前
家里设备越来越多,如何用一张空间地图控制灯光和温度![
android·java·前端·javascript·人工智能·电脑
晚风叙码7 小时前
MySQL 数据类型详解:从数值到字符串,一篇讲透
android·mysql·adb
传奇开心果编程7 小时前
【Compose Multiplatform 跨端开发学与练】第3课 布局与组件
android·windows·学习·ui·ios·kotlin·composer
传奇开心果编程10 小时前
【Compose Multiplatform 跨端开发学与练】第8课 资源管理与主题
android·windows·学习·ios·kotlin·web·composer
传奇开心果编程11 小时前
【Compose Multiplatform 跨端开发学与练】第9课 测试与调试
android·学习·macos·ios·kotlin·web·composer
传奇开心果编程12 小时前
【Compose Multiplatform 跨端开发学与练】第4课 导航与路由
android·windows·学习·ui·ios·kotlin·composer
传奇开心果编程12 小时前
【Compose Multiplatform 跨端开发学与练】第6课 状态管理与架构
android·学习·ui·ios·架构·kotlin·composer
事圆则缓12 小时前
Android AOSP 定制常见概念:源码目录、系统镜像与刷机流程
android
传奇开心果编程12 小时前
【Compose Multiplatform 跨端开发学与练】第2课 Compose 基础语法
android·windows·学习·ui·ios·kotlin·composer