Jetpeck Hilt介绍——Android中依赖注入简单用法(1)
问题背景
我们之前可能都接触过java spring框架,了解和接触过控制反转(IOC)和依赖注入(DI)的概念,那么,什么是IOC和DI呢? IOC是Inversion of Control的缩写,是面向对象编程中的一种设计原则,可以用来降低代码之间的耦合度。 IOC是什么的控制被反转了呢?其实是获得依赖对象的过程被反转了,控制被反转之后,获得依赖对象的过程由自身管理变为了由IOC容器主动注入。 IOC中最常见的方式叫做依赖注入(Dependency Injection,简称DI),所谓依赖注入,就是由IOC容器在运行期间,动态地将某种依赖关系注入到对象之中。 在java spring框架的开发过程,类获得依赖对象不需要手动的new出来,只要利用@autoWired注解配合spring框架即可自动注入对象。很显然,这种获取依赖对象的方式比我们每次都手动new出来更简洁,同时代码之间的耦合度也大大降低了。Google给我们提供了hilt来实现类似的操作,我们一起看看。
问题分析
话不多说,直接上demo看看hilt的一般使用先。 (1)项目根目录的build.gradle文件中配置Hilt的插件路径
buildscript {
...
dependencies {
...
classpath 'com.google.dagger:hilt-android-gradle-plugin:2.44'
}
}
(2)在app/build.gradle文件中,引入Hilt的插件并添加Hilt的依赖库:
plugins {
...
id 'dagger.hilt.android.plugin'
}
dependencies {
implementation "com.google.dagger:hilt-android:2.44"
kapt "com.google.dagger:hilt-android-compiler:2.44"
...
}
(3)我们自定义的MyApplication类加上@HiltAndroidApp注解,代码如下所示:
@HiltAndroidApp
class MyApplication : Application() {
companion object {
var instance: Application by Delegates.notNull()
}
override fun onCreate() {
super.onCreate()
instance = this
...
}
}
(4)新建需要依赖使用的对象加上@Inject注解,代码如下:
class Truck @Inject constructor() {
companion object {
const val TAG = "TestHilt"
}
fun deliver() {
Log.d(TAG, "Truck is delivering cargo.");
}
}
(5)新建activity文件,加上@AndroidEntryPoint注解,代码如下:
@AndroidEntryPoint
class TestHiltActivity : AppCompatActivity() {
private lateinit var activityTestHiltBinding: ActivityTestHiltBinding
@Inject
lateinit var truck: Truck
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityTestHiltBinding = ActivityTestHiltBinding.inflate(LayoutInflater.from(this))
setContentView(activityTestHiltBinding.root)
doDeliver.setOnClickListener {
truck.deliver()
}
}
}
(6)activity对应的layout布局文件如下:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".view.TestHiltActivity">
<Button
android:id="@+id/doDeliver"
android:text="doDeliver"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</androidx.constraintlayout.widget.ConstraintLayout>
运行项目代码,点击按钮,运行结果如下:
问题解决
(1)hilt注入点有哪些? 我们刚才demo使用注解的时候可以看到,只有Application这个入口点是@HiltAndroidApp注解来声明的,这个我们刚才已经看过了。activity是用@AndroidEntryPoint注解来声明的。hilt呢一共6个入口点,分别是: Application Activity Fragment View Service BroadcastReceiver 其中,只有Application这个入口点是使用@HiltAndroidApp注解来声明的,这个我们刚才已经看过了。其他的所有入口点,都是用@AndroidEntryPoint注解来声明的。 (2)@AndroidEntryPoint注解了Activity之后Hilt帮我们做了什么? 生成对应的Hilt_TestHiltActivity.java文件,在inject方法中通过injectTestHiltActivity将我们的TestHiltActivity注入到了ActivityComponent组件中,代码如下: composer.view.Hilt_TestHiltActivity#inject
protected void inject() {
if (!injected) {
injected = true;
((TestHiltActivity_GeneratedInjector) this.generatedComponent()).injectTestHiltActivity(UnsafeCasts.<TestHiltActivity>unsafeCast(this));
}
}
composer.view.TestHiltActivity_GeneratedInjector#injectTestHiltActivity
@OriginatingElement(
topLevelClass = TestHiltActivity.class
)
@GeneratedEntryPoint
@InstallIn(ActivityComponent.class)
public interface TestHiltActivity_GeneratedInjector {
void injectTestHiltActivity(TestHiltActivity testHiltActivity);
}
问题总结
本文主要是介绍了jetpeck库中hilt的简单使用,使用hilt,通过注解的方式依赖注入,可以有效的简化代码,极大降低安卓项目中代码之间的耦合性,有兴趣的同学可以进一步深入研究。