转载请注明出处:https://blog.csdn.net/jiyisuifeng222/article/details/117464197
本文同步发表于我的微信公众号,扫一扫文章底部的二维码或在微信搜索 情花打雪 即可关注,每个工作日都有文章更新。
一个类里有两个变量,这两个变量就是它的依赖。
或者说,当前类依赖这两个变量。
public class CartSkuViewParam {
public CartResponseSku sku;
public CartSkuData data;
}
那么,如何初始化依赖?
要初始化一个依赖,有两种方法
第一,这个类自己来初始化
第二,让外部来帮你初始化
其中,第二种就叫依赖注入
总结一下:关键在于初始化工作是谁做的
下面看几个场景代码片段是否属于依赖注入
class ProductFactory{
public Product newProduct(){
Product product = new Product();
product.id = "100874";
product.name = "名称";
return product;
}
}
//创建对象
ProductFactory factory = new ProductFactory();
Product product = factory.newProduct();
public class Student {
private int id;
private String name;
private String sex;
public static class Builder {
private int id;
private String name;
private String sex;
public Builder() {
}
public Builder id(int id) {
this.id = id;
return this;
}
public Builder name(String name) {
this.name = name;
return this;
}
public Builder sex(String sex) {
this.sex = sex;
return this;
}
public Student build() {
return new Student(this);
}
}
private Student(Builder builder) {
this.id = builder.id;
this.name = builder.name;
this.sex = builder.sex;
}
}
调用
Student student = new Student.Builder()
.id(1).name("ethan").sex("男").build();
public class User {
public String id;
public String name;
public String from;
public User(String id, String name, String from) {
this.id = id;
this.name = name;
this.from = from;
}
}
总结:以上统统都属于依赖注入。神奇吧。
将会触发 Hilt 的代码生成,作为程序依赖项容器的基类
使用 @Inject 来告诉 Hilt 如何提供该类的实例,常用于构造方法,非私有字段,方法中。
module 是用来提供一些无法用 构造@Inject 的依赖,如第三方库,接口,build 模式的构造等。
使用 @Module 注入的类,需要使用 @InstallIn 注解指定 module 的范围
常用于被 @Module 注解标记类的内部方法上。并提供依赖项对象。
@InstallIn(ApplicationComponent.class) 注解的 Module 就会绑定到 Application 的生命周期上。
Hilt组件 | 对应 Android 类活动的范围 |
---|---|
ApplicationComponent | Application |
ActivityRetainedComponent | ViewModel |
ActivityComponent | Activity |
FragmentComponent | Fragment |
ViewComponent | View |
ViewWithFragmentComponent | View annotated with @WithFragmentBindings |
ServiceComponent | Service |
注意:Hilt 不会为广播接收器生成组件,因为 Hilt 直接从 ApplicationComponent 注入广播接收器。
Hilt 会根据相应的 Android 类生命周期自动创建和销毁组件类的实例,对应关系如下:
生成的组件 | 创建时机 | 销毁时机 |
---|---|---|
ApplicationComponent | Application#onCreate() | Application#onDestroy() |
ActivityRetainedComponent | Activity#onCreate() | Activity#onDestroy() |
ActivityComponent | Activity#onCreate() | Activity#onDestroy() |
FragmentComponent | Fragment#onAttach() | Fragment#onDestroy() |
ViewComponent | View#super() | 视图销毁时 |
ViewWithFragmentComponent | View#super() | 视图销毁时 |
ServiceComponent | Service#onCreate() | Service#onDestroy() |
1.环境集成
将 hilt-android-gradle-plugin 插件添加到项目的根级 build.gradle 文件中:
buildscript {
dependencies {
classpath 'com.google.dagger:hilt-android-gradle-plugin:2.28-alpha'
}
}
2.应用 Gradle 插件并在 app/build.gradle 文件中添加以下依赖项:
apply plugin: 'dagger.hilt.android.plugin’
dependencies {
implementation ‘com.google.dagger:hilt-android:2.28-alpha‘
annotationProcessor 'com.google.dagger:hilt-android-compiler:2.28-alpha'
}
3.使用 Hilt 的应用都必须包含一个带有 @HiltAndroidApp 注释的 Application 类
@HiltAndroidApp
public class MyApp extends Application {
}
public class User {
public String id;
public String name;
public String from;
@Inject
public User(){
this("1","lisi", "购物车");
}
public User(String id, String name, String from) {
this.id = id;
this.name = name;
this.from = from;
}
}
代码调用:
@AndroidEntryPoint
public class MainActivity extends AppCompatActivity {
private TextView showText;
@Inject
User user;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
showText = findViewById(R.id.showText);
showText.setText(user.name+" 来自 "+user.from);
}
}
@Module
@InstallIn(ApplicationComponent.class)
class AppModule {
@Singleton
@Provides
public ExecutorService provideExecutor() {
return new ThreadPoolExecutor(5, 30, 1, TimeUnit.MINUTES, new LinkedBlockingDeque(10000));
}
}
代码调用:
@AndroidEntryPoint
public class MainActivity extends AppCompatActivity {
@Inject
ExecutorService executorService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
executorService.execute(new Runnable() {
@Override
public void run() {
……….
}
});
}
}
场景描述:activity会把一些用于显示的数据共享给它内部的那些view和fragment
通常是去获取外部activity对象然后强转,再去拿它内部的对像。
class CustomView extends View {
public CustomView(Context context) {
super(context);
init(context);
}
public void init(Context context) {
if (context instanceof MainActivity) {
User user = ((MainActivity) context).user;
}
}
}
public class MainActivity extends AppCompatActivity {
User user;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//showText = findViewById(R.id.showText);
}
}
使用Hilt,可以把对象直接自动注入
@AndroidEntryPoint
class CustomView extends AppCompatTextView {
@Inject
User user;
public CustomView(Context context) {
super(context);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
setText(user.name);
}
}
代码调用:
@ActivityScoped
public class User {
public String id;
public String name;
public String from;
@Inject
public User(){
this("1","lisi", "购物车");
}
public User(String id, String name, String from) {
this.id = id;
this.name = name;
this.from = from;
}
}
Binds:必须注释一个抽象函数,抽象函数的返回值是实现的接口。
通过添加具有接口实现类型的唯一参数来指定实现。
public interface Person {
String getName();
}
class PersonImpl implements Person {
@Inject
public PersonImpl(){
}
@Override
public String getName() {
return "使用 @Binds 进行接口注入";
}
}
@Module
@InstallIn(ApplicationComponent.class)
abstract class PersonModule {
@Binds
abstract Person getPerson(PersonImpl person);
}
代码调用:
@AndroidEntryPoint
public class MainActivity extends AppCompatActivity {
private TextView showText;
@Inject
Person person;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
showText = findViewById(R.id.showText);
showText.setText(person.getName());
}
}
@Qualifier
public @interface A {
}
class PersonAImpl implements Person {
@Inject
public PersonAImpl(){
}
@Override
public String getName() {
return "PersonAImpl使用 @Qualifier 提供同一接口,不同的实现";
}
}
@Module
@InstallIn(ApplicationComponent.class)
abstract class PersonAModule {
@A
@Singleton
@Binds
abstract Person getPerson(PersonAImpl person);
}
@Qualifier
public @interface B {
}
class PersonBImpl implements Person {
@Inject
public PersonBImpl(){
}
@Override
public String getName() {
return "PersonBImpl使用 @Qualifier 提供同一接口,不同的实现";
}
}
@Module
@InstallIn(ActivityComponent.class)
abstract class PersonBModule {
@B
@ActivityScoped
@Binds
abstract Person getPerson(PersonBImpl person);
}
代码调用:
@AndroidEntryPoint
public class MainActivity extends AppCompatActivity {
private TextView showText;
@A
@Inject
Person personA;
@B
@Inject
Person personB;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
showText = findViewById(R.id.showText);
showText.setText(personA.getName() +"\n"+personB.getName());
}
}
整体体验下来,感觉上手成本比较低,比起dagger,简直不能再爽了。老铁们可以使用使用,解放项目中大批量的重复代码。
需要完整代码Demo私信公众号:“Hilt上车”