程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

android jetpack hilt组件使用dagger

发布于2021-05-29 18:56     阅读(752)     评论(0)     点赞(29)     收藏(4)


参考

https://developer.android.google.cn/training/dependency-injection/hilt-android

尤其要注意 studio4.2.1上是不能跑官网文档中的hilt版本的

我使用的依赖版本配置

1、根gradle依赖

  1. ext.kotlin_version = "1.5.0"//kotlin版本
  2. ext.hilt_version = '2.35'//hilt版本
  3. repositories {
  4.    google()
  5.    mavenCentral()
  6. }
  7. dependencies {
  8.    classpath "com.android.tools.build:gradle:4.2.1"
  9.    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
  10.    classpath 'com.google.dagger:hilt-android-gradle-plugin:2.35'
  11. }

2、app gradle依赖

  1. implementation "com.google.dagger:hilt-android:$hilt_version"
  2. kapt "com.google.dagger:hilt-android-compiler:$hilt_version"

3、所使用的插件

  1. id 'kotlin-kapt'
  2. id 'kotlin-android-extensions'

代码地址

https://github.com/ymeddmn/HiltDaggerDemo

official分支:抄的官网的demo

onlysampletest:最简单的hilt使用

hilt相关的注解

@HiltAndroidApp:所有使用hilt的应用都需要使用这个注解,被使用在Application类上

@AndroidEntryPoint: Hilt可以为带有 @AndroidEntryPoint 注释的其他 Android 类提供依赖项,@AndroidEntryPoint可以被用在四大组件以及View上面

@Inject:获取依赖

@HiltAndroidApp使用举例

  1. @HiltAndroidApp
  2. class App: Application() {
  3.    override fun onCreate() {
  4.        super.onCreate()
  5.   }
  6. }

@AndroidEntryPoint和@Inject使用举例

  1. @AndroidEntryPoint
  2. public class ExampleActivity extends AppCompatActivity {
  3.  @Inject
  4.  AnalyticsAdapter analytics;
  5. ...
  6. }

hilt基本使用

必须配置选项

Application中添加注解

  1. @HiltAndroidApp
  2. class App: Application() {
  3. }

onlysampletest分支代码详解

这个分支实现的功能是在MainActivity中注入Car对象

1、首先加入必须配置选项

2、Car对象代码:

  1. class Car @Inject constructor() {
  2.    fun drive(name: String) {
  3.        println("老司机$name 在线开车")
  4.   }
  5. }
//Car的构造使用@Inject表示Car对象是一个可被注入的对象

3、MainActivity代码:

  1. @AndroidEntryPoint
  2. class MainActivity : AppCompatActivity() {
  3.    @Inject
  4.    lateinit var car: Car//Car对象使用@Inject注解,会自动被实例化,这里必须使用lateinit延迟初始化才会有效
  5.    override fun onCreate(savedInstanceState: Bundle?) {
  6.        super.onCreate(savedInstanceState)
  7.        setContentView(R.layout.activity_main)
  8.        car.drive("mage")
  9.   }
  10. }

代码运行后日志输出:

2021-05-27 21:02:49.874 14104-14104/com.mage.hiltdaggerdemo I/System.out: 老司机mage 在线开车

complextest分支代码详解(更复杂一些的使用)

场景

onlysampletest分支中我们简单的将Car注入到了MainActivity中,但是实际的业务场景我们面临的业务肯定是远比这个负责的,比如我们现在想给Car分配一个司机。正常情况下我们会创建一个Driver司机对象,然后再Car对象的构造函数中传入Driver司机对象。

但是这明显不是hilt所想要的

hilt的场景实现

下面说一下hilt的实现方式:

首先我们需要创建多个类

App Car Driver DriverImpl DriverModule MainActivity

Car的构造中会传入Driver的实现,

Driver是司机的抽象实现,是一个接口。

DriverImple是Driver的实现类可以是任何一个具体的司机。

DriverModule负责提供Driver类的注入规则

下面是代码展示:

1、添加必须配置选项

2、Car实现

  1. class Car @Inject constructor(val driver: Driver) {//Car的构造函数中增加了Driver司机对象的实现
  2.    fun drive() {
  3.        println("老司机${driver.name} 在线开车")
  4.   }
  5. }

2、Driver司机接口

  1. interface Driver {
  2.    val name :String
  3. }

3、DriverImple司机接口的实现

  1. class DriverImpl @Inject constructor() : Driver {//因为DriverImpl需要被注入到Car的构造中,所以DriverImpl本身一个是被注入着,他的构造中也需要使用@Inject注解
  2.    override val name: String
  3.        get() = "mage"
  4. }

4、DriverModule 配置Driver的注入规则

  1. @Module//必须配置的注解,表示这个对象是Module的配置规则
  2. @InstallIn(ActivityComponent::class)//表示这个module中的配置是用来注入到Activity中的
  3. abstract class DriverModule {
  4.    @Binds
  5.    abstract fun bindDriver(driver: DriverImpl): Driver//形参中的DriverImple表示真实要注入Car构造方法中的Driver实现,返回值Driver表示DriverImple所实现的抽象接口
  6. }

5、MainActivity代码

  1. @AndroidEntryPoint
  2. class MainActivity : AppCompatActivity() {
  3.    @Inject
  4.    lateinit var car: Car//这里必须使用lateinit延迟初始化才会有效
  5.    override fun onCreate(savedInstanceState: Bundle?) {
  6.        super.onCreate(savedInstanceState)
  7.        setContentView(R.layout.activity_main)
  8.        car.drive()
  9.   }
  10. }

6、日志输出

2021-05-27 21:30:43.462 18874-18874/com.mage.hiltdaggerdemo I/System.out: 老司机mage 在线开车

 

provider分支代码

provider分支是对@Provides注解的解释

 

complextest中我们使用@Binds注解将我们自定义的对象共享出去,那么如果要共享的对象并非是我们自己创建的(例如OkhttpClient和Request)我们该如何处理呢,这个时候就可以使用@Provides了。代码示例如下:

1、添加必须配置选项

2、创建OkhttpModule

  1. @Module
  2. @InstallIn(ActivityComponent::class)
  3. object OkhttpModule {
  4.    @Provides
  5.    fun provideOkhttpClient(
  6.        // Potential dependencies of this type
  7.   ): OkHttpClient {
  8.        return OkHttpClient()
  9.   }
  10.    @Provides
  11.    fun providdeRequest():Request{
  12.        return Request.Builder()
  13.           .get()
  14.           .url("https://developer.android.google.cn/training/dependency-injection/hilt-android")
  15.           .build()
  16.   }
  17. }

3、MainActivity代码

  1. @AndroidEntryPoint
  2. class MainActivity : AppCompatActivity() {
  3.    @Inject
  4.    lateinit var client: OkHttpClient
  5.    @Inject
  6.    lateinit var request: Request
  7.    override fun onCreate(savedInstanceState: Bundle?) {
  8.        super.onCreate(savedInstanceState)
  9.        setContentView(R.layout.activity_main)
  10.        btn.setOnClickListener {
  11.            client.newCall(request).enqueue(object :Callback{
  12.                override fun onFailure(call: Call, e: IOException) {
  13.                    println("请求失败")
  14.               }
  15.                override fun onResponse(call: Call, response: Response) {
  16.                    println("请求成功")
  17.               }
  18.           })
  19.       }
  20.   }
  21. }

4、日志输出

2021-05-28 07:36:25.477 14692-14775/com.mage.hiltdaggerdemo I/System.out: 请求成功

Hilt进阶使用

multipleobjtest分支使用(同一类型提供多实现)

有些场景,同一类型的对象我们可能会提供多个实例,这个时候就需要特殊处理。举例:

比如我们现在提供一个Car的接口抽象,然后同时给Car提供两个接口实现TruckCar和TaxtCar。在MainActivity中代码如下:

  1. @Inject
  2. lateinit var truck: Car
  3. @Inject
  4. lateinit var taxi: Car

因为注入的对象类型都是Car,所以编译过程中就无法区分我们到底想注入TruckCar还是TaxtCar,所以编译过程中代码就好报错。要解决这个问题就需要使用自定义注解,下面晒代码:

1、必须配置选项

2、Car、TruckCar、TaxiCar代码

  1. interface Car {
  2.    fun drive(name:String)
  3. }
  4. class TruckCar @Inject  constructor():Car{
  5.    override fun drive(name: String) {
  6.        println("$name 卡车老司机开车,呜呜")
  7.   }
  8. }
  9. class TaxiCar @Inject  constructor():Car{
  10.    override fun drive(name: String) {
  11.        println("$name 出租车老司机开车,呜呜")
  12.   }
  13. }

3、CarModule代码

  1. @Qualifier
  2. @Retention(AnnotationRetention.BINARY)
  3. annotation class Truck//卡车类注入标记
  4. @Qualifier
  5. @Retention(AnnotationRetention.BINARY)
  6. annotation class Taxi//出租车类注入标记
  7. @Module
  8. @InstallIn(ActivityComponent::class)
  9. class CarModule {
  10.    @Truck//卡车类生成规则加上这个注解,注入的时候也是用该注解编译器就可以知道我们真实想注入的类型是TruckCar
  11.    @Provides
  12.    fun bindTruckCar(truckCar: TruckCar): Car {
  13.        return TruckCar()
  14.   }
  15.    @Taxi//出租车类生成规则加上这个注解,注入的时候也是用该注解编译器就可以知道我们真实想注入的类型是TaxiCar
  16.    @Provides
  17.    fun bindTaxtCar(taxiCar: TaxiCar): Car {
  18.        return TaxiCar()
  19.   }
  20. }

4、日志输出

2021-05-28 08:12:28.780 20418-20418/com.mage.hiltdaggerdemo I/System.out: mage 卡车老司机开车,呜呜 2021-05-28 08:12:28.780 20418-20418/com.mage.hiltdaggerdemo I/System.out: mage 出租车老司机开车,呜呜

预定义限定符(@ApplicationContext @ActivityContext)

抄一下官方的解释,Hilt 提供了一些预定义的限定符。例如,由于您可能需要来自应用或 Activity 的 Context 类,因此 Hilt 提供了 @ApplicationContext@ActivityContext 限定符。

代码示例:

1、必须配置选项

2、BaseInfo类

  1. class BaseInfo @Inject constructor(@ActivityContext private val context: Context) {
  2.    fun printPackageName(){
  3.        println("应用包名 ${context.packageName}")
  4.   }
  5. }

3、MainActivity类

  1. @AndroidEntryPoint
  2. class MainActivity : AppCompatActivity() {
  3.    @Inject
  4.    lateinit var baseInfo: BaseInfo
  5.    override fun onCreate(savedInstanceState: Bundle?) {
  6.        super.onCreate(savedInstanceState)
  7.        setContentView(R.layout.activity_main)
  8.        btn.setOnClickListener {
  9.            baseInfo.printPackageName()
  10.       }
  11.   }
  12. }

4、日志输出

2021-05-28 08:20:56.292 21928-21928/com.mage.hiltdaggerdemo I/System.out: 应用包名 com.mage.hiltdaggerdemo

官方提供的类生成组件(抄官方)

对于您可以从中执行字段注入的每个 Android 类,都有一个关联的 Hilt 组件,您可以在 @InstallIn 注释中引用该组件。每个 Hilt 组件负责将其绑定注入相应的 Android 类。

所有组件如下,组件的生命周期和是依赖于注入组件类的生命周期的

ApplicationComponentApplication 
ActivityRetainedComponentViewModel作用于ViewModel
ActivityComponentActivity 
FragmentComponentFragment 
ViewComponentView 
ViewWithFragmentComponent带有 @WithFragmentBindings 注释的 View 
ServiceComponentService 

组件作用域(抄官方)

默认情况下,Hilt 中的所有绑定都未限定作用域。这意味着,每当应用请求绑定时,Hilt 都会创建所需类型的一个新实例。

不过,Hilt 也允许将绑定的作用域限定为特定组件。Hilt 只为绑定作用域限定到的组件的每个实例创建一次限定作用域的绑定,对该绑定的所有请求共享同一实例。

比如当组件作用域为@Singleton的时候,这个组件就是一个全局单例的

比如当组件作用域为@ActivityScoped的时候,这个组件在同一个Activity内都是同一个对象实例

所以默认的组件和作用域

Android 类生成的组件作用域
ApplicationApplicationComponent@Singleton
View ModelActivityRetainedComponent@ActivityRetainedScope
ActivityActivityComponent@ActivityScoped
FragmentFragmentComponent@FragmentScoped
ViewViewComponent@ViewScoped
带有 @WithFragmentBindings 注释的 ViewViewWithFragmentComponent@ViewScoped
ServiceServiceComponent@ServiceScoped

 

组件默认绑定(抄官方)

Android 组件默认绑定
ApplicationComponentApplication
ActivityRetainedComponentApplication
ActivityComponentApplicationActivity
FragmentComponentApplicationActivityFragment
ViewComponentApplicationActivityView
ViewWithFragmentComponentApplicationActivityFragmentView
ServiceComponentApplicationService

 

 

 

原文链接:https://blog.csdn.net/ymeddmn/article/details/117338786



所属网站分类: 技术文章 > 博客

作者:我爱编程

链接:http://www.javaheidong.com/blog/article/207121/2289b47bd2d3a0737493/

来源:java黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

29 0
收藏该文
已收藏

评论内容:(最多支持255个字符)