Android Hilt依赖注入的使用讲解

作者:FranzLiszt1847 时间:2023-11-23 02:13:50 

什么是依赖注入

首先,某个类的成员变量称为依赖,如若此变量想要实例化引用其类的方法,可以通过构造函数传参或者通过某个方法获取对象,此等通过外部方法获取对象实例的称为依赖注入;而依赖注入又可以简单分为手动注入和自动注入两种方式;Hilt就是基于Dagger进行场景化优化的一个依赖注入库,Hilt是Google专门为Android平台打造的一个依赖注入库,在使用上极大程度进行啦简化(与dagger相比)

使用依赖注入的好处

Google文档中介绍的优势如下:

  • 重用代码

  • 易于重构

  • 易于测试

简单来说,在开发中某些内容需要进行层层手动调用,而且需要手动进行实例化;对于Hilt而言,它可以自动进行依赖注入,并且为项目中的每个 Android 类提供容器并自动管理其生命周期;某些需要全局使用的数据,可以通过Hilt进行共享,从而简化代码

Hilt中常用的预定义限定符

@HiltAndroidApp

所有使用 Hilt 的应用都必须包含一个带有 @HiltAndroidApp 注解的 Application 类。@HiltAndroidApp 会触发 Hilt 的代码生成操作,生成的代码包括应用的一个基类,该基类充当应用级依赖项容器,记得此Application类要在清单文件中进行引用

@HiltAndroidApp
class App : Application() { ... }

@AndroidEntryPoint

如果某个Activity要使用Hilt依赖注入,就必须给Activity添加@AndroidEntryPoint注解,同理Activity中的某个Fragment也需要使用,也必须添加@AndroidEntryPoint注解

目前Hilt 支持以下 Android 类:

  • Application(通过使用 @HiltAndroidApp)

  • ViewModel(通过使用 @HiltViewModel)

  • Activity

  • Fragment

  • View

  • Service

  • BroadcastReceiver

@AndroidEntryPoint
class MainActivity : ComponentActivity() {...}

@Module

Hilt带有一个模块的类,使用@Module注解的类,它会告知Hilt,它提供了哪些实例,通常和@Provider搭配使用,必须通过@InstallIn注解为其添加作用域

@InstallIn

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

Android 组件默认绑定
SingletonComponentApplication
ActivityRetainedComponentApplication
ViewModelComponentSavedStateHandle
ActivityComponentApplication 和 Activity
FragmentComponentApplication、Activity 和 Fragment
ViewComponentApplication、Activity 和 View
ViewWithFragmentComponentApplication、Activity、Fragment 和 View
ServiceComponentApplication 和 Service
@Module
@InstallIn(SingletonComponent::class)
object AppModule {...}

@Provides

如果想要让Hilt知道,提供了哪些实例对象,可以使用@Provides进行注解,以下提供啦一个数据库实例,并且作用域是全局单例

@Provides
   @Singleton
   fun providerAccountBean():AccountBean{
       return AccountBean("FranzLiszt","123456")
   }

@Inject

如果想要使用Hilt自动进行啦依赖注入的对象,可以使用@Inject注解进行调用;如下,无需进行实例化,它会自动引用providerAccountBean()提供的对象

@Inject lateinit var bean: AccountBean

@HiltViewModel

通过名称就可以了解,它需要与ViewModel类联合使用,作用于ViewModel上;如下,与@Inject结合使用,在构造函数引用啦上述Hilt提供的对象

@HiltViewModel
class AccountViewModel @Inject constructor(private val bean: AccountBean):ViewModel() {...}

Hilt的使用

依赖

第一步:在project/build.gradle中添加如下代码

plugins {
    ...
    id 'com.google.dagger.hilt.android' version '2.44' apply false
}

第二步:在app/build.gradle中添加如下代码

plugins {
    ...
    id 'kotlin-kapt'
    id 'dagger.hilt.android.plugin'
}

第三步:在app/build.gradle中添加如下代码

   //Dagger - Hilt
    implementation("com.google.dagger:hilt-android:2.44")
    kapt("com.google.dagger:hilt-android-compiler:2.44")

    // Compose dependencies
    implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.4.0-beta01"
    implementation "androidx.hilt:hilt-navigation-compose:1.0.0-alpha03"

第四步:在app/build.gradle中添加如下代码

android{
...
 compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

建立实体类

data class AccountBean(var username:String,var password:String)

添加Hilt入口

@HiltAndroidApp
class APP:Application() {}

提供对象

此处作为用例,只是简单写一个测试用例,在函数中可以编写复杂的程序,并不会影响程序性能,在程序初始化编译时会耗时一丢丢。一下提供啦单例AccountBean对象

@Module
@InstallIn(SingletonComponent::class)
object AppModule {
   @Provides
   @Singleton
   fun providerAccountBean():AccountBean{
       return AccountBean("FranzLiszt","123456")
   }
}

获取对象

给Activity添加HiltAndroidEntryPoint注解,然后可以通过Inject注解获取上面providerAccountBean方法提供的对象

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
   @Inject lateinit var bean: AccountBean
   ...
   }

然后就可以直接进行对象引用

@Composable
   fun showAccountInfo() {
       Column(
           verticalArrangement = Arrangement.Center,
           horizontalAlignment = Alignment.CenterHorizontally
       ) {
           Text(text = bean.username)
           Spacer(modifier = Modifier.height(20.dp))
           Text(text = bean.password)
       }
   }

应用与ViewModel中

在ViewModel中使用HiltViewModel注解,然后就可以使用Inject注解获取Hilt自动注入依赖的对象

@HiltViewModel
class AccountViewModel @Inject constructor(private val bean: AccountBean):ViewModel() {...}

定义两个具有状态的成员变量,其中AccountState是一个数据类,具有text和hint两个成员变量

private val _usernameState = mutableStateOf(AccountState(
       hint = "input username"
   ))
   val usernameState:State<AccountState> = _usernameState
   private val _passwordState = mutableStateOf(AccountState(
       hint = "input password"
   ))
   val passwordState:State<AccountState> = _passwordState

在ViewModel初始化函数中,将Hilt提供的对象的值赋值给VM中的两个状态变量

init {
       _usernameState.value = usernameState.value.copy(text = bean.username)
       _passwordState.value = passwordState.value.copy(text = bean.password)
   }

通过外部事件进行对应处理,外部输入框不断进行值修改,此处同步给VM中的状态变量

fun onEvent(event: AccountEvent){
       when(event){
           is AccountEvent.ChangeUsername ->{
               _usernameState.value = usernameState.value.copy(text = event.value)
           }
           is AccountEvent.ChangePassword ->{
               _passwordState.value = passwordState.value.copy(text = event.value)
           }
       }
   }

使用

此处直接获取ViewModel的两个成员变量值,然后与两个输入框进行绑定,通过监听输入框的onValueChange方法,当其值不断修改时,然后调用VM中的onEvent方法,然后修改VM中的状态内容,由于输入框绑定了VM的状态变量,然后状态变量值改变后,相对应的UI界面会进行重组

@Composable
   fun showAccountInfo (viewModel: AccountViewModel = hiltViewModel()){
       val username = viewModel.usernameState.value
       val password = viewModel.passwordState.value
       Column(
           verticalArrangement = Arrangement.Center,
           horizontalAlignment = Alignment.CenterHorizontally
       ) {
           TextField(
               value = username.text,
               placeholder = { Text(text = username.hint)},
               onValueChange = {
                   viewModel.onEvent(AccountEvent.ChangeUsername(it))
               }
           )
           Spacer(modifier = Modifier.height(20.dp))
           TextField(
               value = password.text,
               placeholder = { Text(text = password.hint)},
               onValueChange = {
                   viewModel.onEvent(AccountEvent.ChangePassword(it))
               }
           )
       }
   }

来源:https://blog.csdn.net/News53231323/article/details/128554310

标签:Android,Hilt,依赖注入
0
投稿

猜你喜欢

  • Winform窗体中打开PDF文件的三种方式

    2023-05-15 19:46:52
  • 如何搭建新的WPF项目框架

    2023-09-28 08:18:05
  • JVM常用垃圾收集器详细解说

    2023-02-15 02:19:49
  • Spring使用三级缓存解决循环依赖的问题

    2023-03-14 09:06:15
  • Android实现内存中数据保存到sdcard的方法

    2022-06-12 21:02:09
  • android学习笔记之View的滑动

    2022-12-30 07:51:36
  • Java异常处理机制try catch流程详解

    2022-09-23 08:51:09
  • 详解Mybatis Generator的具体使用教程

    2022-01-16 22:39:13
  • Android仿微信语音消息的录制和播放功能

    2022-08-15 09:28:32
  • android开发教程之子线程中更新界面

    2022-11-17 04:41:42
  • Android如何通过scheme跳转界面

    2021-08-11 05:19:41
  • 利用Java自写一个生成ID的工具类

    2023-04-24 04:10:08
  • 浅谈idea live template高级知识_进阶(给方法,类,js方法添加注释)

    2023-12-07 22:50:28
  • Kotlin编程基础语法编码规范

    2023-06-20 16:50:07
  • Android自定义带增长动画和点击弹窗提示效果的柱状图DEMO

    2022-10-16 17:10:25
  • Java中try、catch的使用方法

    2021-11-08 00:48:12
  • 基于Flutter实现爱心三连动画效果

    2023-09-02 03:38:36
  • android获取屏幕宽高与获取控件宽高(三种方法)

    2022-07-11 11:25:42
  • SSh结合Easyui实现Datagrid的分页显示

    2022-01-14 21:46:49
  • Java深入浅出理解快速排序以及优化方式

    2023-01-17 13:50:44
  • asp之家 软件编程 m.aspxhome.com