Jetpack成员Hilt依赖注入框架简析

转载请注明出处:https://blog.csdn.net/jiyisuifeng222/article/details/117464197

本文同步发表于我的微信公众号,扫一扫文章底部的二维码或在微信搜索 情花打雪 即可关注,每个工作日都有文章更新。

Jetpack成员Hilt依赖注入框架简析

  • 什么是Hilt?
        • 依赖注入库,是专门针对于Android平台的依赖注入库,它是基于dagger。
        • 更确切的说:就是用注解来进行配置的依赖注入库。
  • Hilt有什么用?
      • 什么是依赖注入?
      • 初始化依赖的方法
        • 工厂的使用
        • Builder模式
        • 带参数的构造函数
        • Hilt针对Android开发制定了一系列的规则,通过这些规则大大简化了这套工具的使用。***更方便地使用依赖注入***
  • Hilt常用注解
      • @HiltAndroidApp
      • @Inject
      • @Module
      • @InstallIn
      • @Provides
  • Hilt组件及组件生命周期
  • Hilt使用场景介绍
    • 如何使用Hilt
    • 场景1:使用Hilt对类进行依赖注入
    • 场景2:使用Hilt对全局共享对象、第三方组件依赖注入
    • 场景3:使用Hilt对局部共享对象依赖注入
    • 场景4:使用 @Binds 进行接口注入
    • 场景5:使用 @Qualifier 提供同一接口,不同的实现
  • Hilt总结

什么是Hilt?

依赖注入库,是专门针对于Android平台的依赖注入库,它是基于dagger。

更确切的说:就是用注解来进行配置的依赖注入库。

Hilt有什么用?

什么是依赖注入?

一个类里有两个变量,这两个变量就是它的依赖。
或者说,当前类依赖这两个变量。

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();

Builder模式

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针对Android开发制定了一系列的规则,通过这些规则大大简化了这套工具的使用。更方便地使用依赖注入

Hilt常用注解

@HiltAndroidApp

将会触发 Hilt 的代码生成,作为程序依赖项容器的基类

@Inject

使用 @Inject 来告诉 Hilt 如何提供该类的实例,常用于构造方法,非私有字段,方法中。

@Module

module 是用来提供一些无法用 构造@Inject 的依赖,如第三方库,接口,build 模式的构造等。

@InstallIn

使用 @Module 注入的类,需要使用 @InstallIn 注解指定 module 的范围

@Provides

常用于被 @Module 注解标记类的内部方法上。并提供依赖项对象。

Hilt组件及组件生命周期

@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()

Hilt使用场景介绍

如何使用Hilt

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 {
}

场景1:使用Hilt对类进行依赖注入

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);
    }
} 

场景2:使用Hilt对全局共享对象、第三方组件依赖注入

@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() {
  ……….
            }
        });
    }
}   

场景3:使用Hilt对局部共享对象依赖注入

场景描述: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;
    }
}

场景4:使用 @Binds 进行接口注入

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());
    }
}

场景5:使用 @Qualifier 提供同一接口,不同的实现

@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());
    }
}

Hilt总结

整体体验下来,感觉上手成本比较低,比起dagger,简直不能再爽了。老铁们可以使用使用,解放项目中大批量的重复代码。

需要完整代码Demo私信公众号:“Hilt上车”

关注我的技术公众号,每天都有优质技术文章推送。
微信扫一扫下方二维码即可关注:
Jetpack成员Hilt依赖注入框架简析_第1张图片

你可能感兴趣的:(新技术探索,android,kotlin,java,flutter)