美文网首页
Android中Hilt的常用场景使用

Android中Hilt的常用场景使用

作者: 安安_660c | 来源:发表于2022-11-24 17:49 被阅读0次

1、依赖版本

依赖版本,这里注意和老版本不同,无需再集成ViewModel拓展依赖了

    implementation 'com.google.dagger:hilt-android:2.38.1'
    kapt 'com.google.dagger:hilt-android-compiler:2.38.1'

根目录依赖插件

    //Hilt插件
    classpath 'com.google.dagger:hilt-android-gradle-plugin:2.38.1'

运行模块加入插件

   apply plugin: 'dagger.hilt.android.plugin'

2、入口定义

Application还是要定义注解

@HiltAndroidApp
class MyApplication : BaseApplication() {
}

3、单例的定义

单例的定义和老版本有所不同

/**
 * 全局的DI注入
 */
@Module
@InstallIn(SingletonComponent::class)
class ApplicationModule {

    //如果是自己定义的MyApplication,通过一个Module向下转型
    @Provides
    fun provideMyApplication(application: Application): MyApplication {
        return application as MyApplication
    }

    //全局的Gson  使用框架进行容错处理
    @Provides
    @Singleton
    fun provideGson(): Gson {
        return GsonFactory.getSingletonGson()
    }

}

使用单例也非常简单,直接注入,它会自己去Scope中一层一层往上找。
@AndroidEntryPoint //如果有东西注入必加的注解

class UserLoginActivity : YYBaseVDBActivity<UserLoginViewModel, ActivityUserLoginBinding>() {
    
    @Inject          //直接注入-一层一层找ActivityScope中找不到 就去ApplicationScop中找 就找到上面定义的那个Gson提供者了
    lateinit var mGson: Gson
    
}

4、ViewModel的注入

Repository:

@Singleton     //构造方法注入 并保持单例
class DemoRepository @Inject constructor() : BaseRepository() {

    suspend inline fun getIndustry(): OkResult<List<Industry>> {
      // xxx
    }

}

@Singleton   //构造方法注入 并保持单例
class SchoolRepository @Inject constructor() : BaseRepository() {

    suspend inline fun getSchool(): OkResult<List<SchoolBean>> {
      //xxx
    }

}

ViewModel:

@HiltViewModel
class UserLoginViewModel @Inject constructor(
    private val mRepository: DemoRepository,
    private val mSchoolRepository: SchoolRepository,       //通过构造方法注入 会自动去找上面的@Inject的构造对象 初始化出来
    private val savedStateHandle: SavedStateHandle         //系统的类 帮助Activity重建保存和恢复状态用的  也是自动注入的
    private val application: Application                   //新版本Application是可以直接使用的
) : BaseViewModel() {
}

Activity

@AndroidEntryPoint
class UserLoginActivity : BaseActivity>() {

    private val viewModel : UserLoginViewModel by viewModels() //通过此委托方法可以直接获取ViewModel对象
    
    //private val viewModel by viewModels<UserLoginViewModel>()   和上面的一样效果

    @Inject
    lateinit var mGson: Gson
    
}

5、自定义对象的注入

自定义对象的注入也是比较常用的,比如Adapter,自定义View,Layout等。
分为简单类注入和复杂类注入。
简单类注入直接构造方法Inject就可以了

@Singleton
class UserDao @Inject constructor(
                                    //3.找到这里 发现这个构造是空参数 直接构造并完成返回
) {

    fun printUser(): String {
        return this.toString()
    }
}
@Singleton
class UserServer @Inject constructor(
    private val userDao: UserDao        //2.找到这里,发现这个构造需要一个UserDao对象,继续查找
) {

    fun testUser() {
        YYLogUtils.w(userDao.printUser())
        toast(userDao.printUser())
    }

    fun getDaoContent(): String {
        return userDao.printUser()
    }

}
@AndroidEntryPoint
class UserLoginActivity : YYBaseVDBActivity<UserLoginViewModel, ActivityUserLoginBinding>() {

    @Inject
    lateinit var userServer: UserServer          //1.由这里开始发起查找
    
}

复杂类的注入,我们可以定义Module

public class Pencil {
    public void sayPencil() {
        YYLogUtils.w("Pencil - i'm pencil");
    }
}
public class Book {

    private Pencil pencil;

    public Book(Pencil pencil) {
        this.pencil = pencil;
    }

    public void sayBook() {
        YYLogUtils.w("Book:" + this.toString());
        pencil.sayPencil();
    }
}

开始注入的中间类,这个是Activity中的生命周期保持单例,如果想全局保持单例 需要@InstallIn(SingletonComponent::class) @Singleton注解方法。
这样虽然复杂一点但是更灵活了

@Module
@InstallIn(ActivityComponent::class)
class AuthDIModel {

    @ActivityScoped
    @Provides
    fun providePencil(): Pencil {    //Activity级别同一个实例
        return Pencil()
    }

    @Provides
    fun provideBook(pencil: Pencil): Book {   //找到这里的时候 发现需要一个Pencil 然后再去找Pencil
        return Book(pencil)
    }

}

使用:

@AndroidEntryPoint
class UserLoginActivity : YYBaseVDBActivity<UserLoginViewModel, ActivityUserLoginBinding>() {

    @Inject
    lateinit var userServer: UserServer  //和下面是两种不同的注入方式 都可以

    @Inject
    lateinit var mBook: Book   //一样的可以用
    
}

6、接口对象的注入

上面的几种注入方式,已经含括了绝大部分场景,另一种比较少见的是接口的实现注入,也是分2中类型,一种是接口单实例的注入和接口多实例的注入
单实例注入:

interface IBook {
    suspend fun saveBook(name: String)

    suspend fun getBookAllSum(): Int
}
class BookImpl @Inject constructor() : IBook {
    @Inject
    lateinit var dao: BookDao
    override suspend fun saveBook(name: String) {
        //这里可能会有一些自己的处理...
        dao.insertAll(Book(name))
    }
  
   override suspend fun getBookAllSum(): Int {
        return dao.queryBookAll()
    }
}

注意这里的 @Module 这里的Class是抽象类,提供实例的注解是 @Binds 而不是 @Provides

@InstallIn(ApplicationComponent::class)
@Module
abstract class BookModel {
    @Binds
    abstract fun bindIBook(impl: BookImpl): IBook   //直接指定到单实例上面
}

使用

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    @Inject
    lateinit var iBook: IBook
}

多实例的注入:
如果是一个接口的多实例,如何注入呢?

interface Engine {
    fun start()
    fun shutdown()
}

多实例:

class GasEngine() @Inject constructor() : Engine {
    override fun start() {
        println("Gas engine start.")
    }

    override fun shutdown() {
        println("Gas engine shutdown.")
    }
}

class ElectricEngine() @Inject constructor() : Engine {
    override fun start() {
        println("Electric engine start.")
    }

    override fun shutdown() {
        println("Electric engine shutdown.")
    }
}

当然要定义标识的自定义注解来标识他们啦 不然怎么知道谁是谁。
当然还有别的方式来标识,这里只是推荐使用这种方式

@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class BindGasEngine

@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class BindElectricEngine

和上面的Mudule一样,只是标识了自定义注解标识

@Module
@InstallIn(ActivityComponent::class)
abstract class EngineModule {
    
    @BindGasEngine
    @Binds
    abstract fun bindGasEngine(gasEngine: GasEngine): Engine              //直接指定到对应的实例上

    @BindElectricEngine
    @Binds
    abstract fun bindElectricEngine(electricEngine: ElectricEngine): Engine  //直接指定到对应的实例上
 
}

使用

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    @BindGasEngine               //指定标识
    @Inject
    lateinit var gasEngine: Engine

    @BindElectricEngine           //指定标识
    @Inject
    lateinit var electricEngine: Engine
}

看到这里是不是觉得Hilt的使用其实也不难,我们在Android的开发场景中,也就用到这些功能,其实都是模板代码,大家可以选择对应的场景复制到自己的项目中改一下相关的对象就可以了。

来自:https://juejin.cn/post/7102956956653977637

相关文章

  • Android中Hilt的常用场景使用

    1、依赖版本 依赖版本,这里注意和老版本不同,无需再集成ViewModel拓展依赖了 根目录依赖插件 运行模块加入...

  • Jetpack - Hilt

    Jetpack - Hilt依赖注入、依赖注入框架Android 常用的依赖注入框架Hilt 的简单使用 1. 依...

  • Jetpack技术Hilt【实现解耦 】

    Hilt是什么? Hilt 是基于 Dagger2 的针对 Android场景定制化 的框架。 这有点像什么? R...

  • Hilt依赖注入

    1.使用 Hilt 实现依赖项注入 | Android 开发者 | Android Developers ...

  • 10 Jetpack-Hilt-1

    通过这篇文章你将学习到以下内容: 为什么需要使用依赖注入库? Hilt 是什么? Hilt 常用注解含义? 使用 ...

  • android中Hilt的使用流程

    依赖注入 Dependency Injection,简称DI; 依赖项注入可以使代码解耦,便于复用,重构和测试 什...

  • 比Dagger2好用一个量级-Hilt的使用和详解

    1 Hilt简介 Hilt 是 Android Jetpack中的依赖注入库,可减少项目代码,用于模块解耦。Hil...

  • Android Hilt使用

    https://developer.android.google.cn/training/dependency-i...

  • Android官方新推的DI库 Hilt

    Android官方新推的DI库 Hilt Hilt是Google Android官方新推荐的依赖注入工具.已加入到...

  • Android Hilt

    Android Hilt使用教程(包含实例)[https://www.jianshu.com/p/f32beb36...

网友评论

      本文标题:Android中Hilt的常用场景使用

      本文链接:https://www.haomeiwen.com/subject/pvexfdtx.html