转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/128424833
本文出自【赵彦军的博客】
https://developer.android.com/training/dependency-injection/hilt-android#groovy
demo 如下:
https://gitee.com/zhaoyanjun/hilt
在根目录 build.gradle
的添加 hilt 插件
plugins {
...
id 'com.google.dagger.hilt.android' version '2.44' apply false
}
完整如下:
plugins {
id 'com.android.application' version '7.3.1' apply false
id 'com.android.library' version '7.3.1' apply false
id 'org.jetbrains.kotlin.android' version '1.7.20' apply false
//添加hilt 依赖
id 'com.google.dagger.hilt.android' version "2.44" apply false
}
在 app 的 build.gradle
,的 plugins
目录添加
...
plugins {
id 'kotlin-kapt'
id 'com.google.dagger.hilt.android'
}
android {
...
}
dependencies {
implementation "com.google.dagger:hilt-android:2.44"
kapt "com.google.dagger:hilt-compiler:2.44"
}
// Allow references to generated code
kapt {
correctErrorTypes true
}
在 Application
添加 @HiltAndroidApp
注解
@HiltAndroidApp
public class App extends Application {
}
使用 @Inject
注解作用在类的构造函数中
public class Util {
String token = "1234444";
@Inject
public Util() {
}
}
在 MainActivity
类中添加 @AndroidEntryPoint
注解
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
}
在 android 项目中,但凡一个类要使用 hilt 依赖注入能力,就要在类头部加入 @AndroidEntryPoint
注解
使用 @Inject
申明需要使用的注入类
@Inject
lateinit var appToken: Util
完整的代码如下:
import android.os.Bundle
import android.util.Log
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
@Inject
lateinit var appToken: Util
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById<TextView>(R.id.tv).text = appToken.token
}
}
这样例子就可以跑起来了。
但是这里有个问题,每一个申明 @Inject lateinit var appToken: Util
的对象都是一个新对象,如果我们要想在 Activity 作用域中实现对象共享,类似于 jetpack 中的 viewModel 。我么需要 @ActivityScoped
注解
代码如下:
@ActivityScoped
public class Util {
String token = "1234444";
@Inject
public Util() {
}
}
使用 @ActivityScoped
修饰的注入类,在 Activity 类多次申明注入,得到的实例只有一个。
全局单例作用域
@Singleton
public class Util {
String token = "1234444";
Context context;
@Inject
public Util(@ApplicationContext Context context) {
this.context = context;
}
public String getName() {
return context.getResources().getString(R.string.app_name);
}
}
作用域只局限于 View , 即时两个 view 有父子关系,那么注入的也是新的实例。
@ViewScoped
public class ViewUtil {
public String token = "1234444";
@Inject
public ViewUtil() {
}
}
举例说明:
<com.zyj.hint.MyViewGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.zyj.hint.MyView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</com.zyj.hint.MyViewGroup>
<com.zyj.hint.MyView2
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
分别在 MyViewGroup 、MyView 、MyView2 注入实例,得到的是三个不同的实力。
viewGroup ViewScoped com.zyj.hint.util.ViewUtil@2b7364f
view1 ViewScoped com.zyj.hint.util.ViewUtil@3aae2e5
view2 ViewScoped com.zyj.hint.util.ViewUtil@5ae86b
完整代码详见:https://gitee.com/zhaoyanjun/hilt
定义共享类
@ViewModelScoped
public class ViewModelUtil {
public String token = "1234444";
@Inject
public ViewModelUtil() {
}
}
在 ViewModel 中申明注入类
@HiltViewModel
class MainViewModel @Inject constructor() : ViewModel() {
@Inject
lateinit var viewModelUtil: ViewModelUtil
fun run() {
Log.d("yu--", "MainViewModel $viewModelUtil")
}
}
Activity 中获取 ViewModel 实例
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModelProvider
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewModel = ViewModelProvider(this)[MainViewModel::class.java]
viewModel.run()
}
}
完整代码详见:https://gitee.com/zhaoyanjun/hilt
如果是 Activity 实例的 context , 需要添加 @ActivityContext
public class Util {
String token = "1234444";
Context context;
@Inject
public Util(Context context) {
this.context = context;
}
public String getName() {
return context.getResources().getString(R.string.app_name);
}
}
但是这种已编译就报错
解决也很好弄,在 Context 上添加 @ApplicationContext
注解,代码如下:
public class Util {
String token = "1234444";
Context context;
@Inject
public Util(@ApplicationContext Context context) {
this.context = context;
}
public String getName() {
return context.getResources().getString(R.string.app_name);
}
}
添加 @ApplicationContext
注解后,Context 参数就会自动添加。
如果是 Activity 实例的 context , 需要添加 @ActivityContext
, 代码如下:
public class Util {
String token = "1234444";
Context context;
@Inject
public Util(@ActivityContext Context context) {
this.context = context;
}
public String getName() {
return context.getResources().getString(R.string.app_name);
}
}