注册

Android 依赖注入 hilt 库的使用

hilt官网


1-什么是控制反转和依赖注入?


IOC(控制反转):全称是 Inverse of Control , 是一种思想.指的是让第3方去控制去创建对象.


DI(依赖注入):全称是 Dependency Injection , 对象的创建是通过注入的方式实现. 是IOC的一种具体实现.


2- 为啥要用依赖注入?


在java中我们创建对象都是通过new Object(), 或者是使用反射泛型进行创建, 需要指定泛型, 需要继承或者实现某接口, 不够灵活, 举个例子: 比如在使用MVVM模式进行网络请求时,我们通常在ViewModel定义Repository层,然后把Api传递给Repository层. 最后在ViewModel中发起接口请求


// 定义网络接口
interface MainApi {
default void requestList() {}
}

// 仓库抽象类
abstract class BaseRepo{}

// 首页仓库
class MainRepo extends BaseRepo {
private MainApi api;
public MainRepo(MainApi api) {
this.api = api;
}
void requestList() {
// 具体调用接口
api.requestList();
}
}

// 抽象ViewModel层
abstract class BaseViewModel {}

// ViewModel层
class MainViewModel extends BaseViewModel {
MainRepo repo = new MainRepo(new MainApi() {});

void requestList(){
// 通过repo请求接口
repo.requestList();
}
}

问题: 每次都要在Model层创建Repository对象和Api对象,这是重复且冗余的.


解决方案: 通过在ViewModel层和Repo层指定泛型,然后反射创建


// 定义网络接口
interface MainApi {
default void requestList() {
}
}

// 仓库抽象类
abstract class BaseRepo<Api> {
private Api api;

public Api getApi() {
return api;
}

public void setApi(Api api) {
this.api = api;
}
}

// 首页仓库
class MainRepo extends BaseRepo<MainApi> {
void requestList() {
// 具体调用接口
getApi().requestList();
}
}

// 抽象ViewModel层
abstract class BaseViewModel<R extends BaseRepo> {
private R repo;

public BaseViewModel() {
try {
repo = crateRepoAndApi(this);
} catch (Exception e) {
e.printStackTrace();
}
}

public R getRepo() {
return repo;
}
// 反射创建Repo和Api
public R crateRepoAndApi(BaseViewModel<R> model) throws Exception {
Type repoType = ((ParameterizedType) model.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
R repo = (R) repoType.getClass().newInstance();
Type apiType = ((ParameterizedType) repoType.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
String apiClassPath = apiType.getClass().toString().replace("class ", "").replace("interface ", "");
repo.setApi(Class.forName(apiClassPath));
return repo;
}
}

// ViewModel层
class MainViewModel extends BaseViewModel<MainRepo> {
void requestList() {
// 通过repo请求接口
getRepo().requestList();
}
}

通过反射可以避免在ViewModel里写new Repo()和new api()的代码. 除了反射还有没有更好的实现方式呢?


image.png


3-jectpack 中 hilt库的使用方法


1-引入包


1-在项目最外层build.gralde引入
classpath 'com.google.dagger:hilt-android-gradle-plugin:2.37'

2-在app模块顶部
plugin "dagger.hilt.android.plugin"
plugin "kotlin-kapt"

3-在app模块内,最外层添加纠正错误类型
kapt {
correctErrorTypes true
}

4-添加依赖
implementation 'com.google.dagger:hilt-android:2.37'
kapt 'com.google.dagger:hilt-compiler:2.37'

2-必须在Application子类上添加注解@HiltAndroidApp


@HiltAndroidApp
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
}
}

@HiltAndroidApp 创建一个容器.该容器遵循 Android 的生命周期类,目前支持的类型是: Activity, Fragment, View, Service, BroadcastReceiver @Inject


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


Hilt 有关如何提供不同类型的实例信息也称之为绑定


@Module


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


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


增加了 @Module 注解的类,其实代表的就是一个模块,并通过指定的组件来告诉在那个容器中可以使用绑定安装。


@InstallIn


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


例如使用 @InstallIn(ActivityComponent::class) 注解的 module 会绑定到 activity 的生命周期上。


@Provides


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


@EntryPoint Hilt 支持最常见的 Android 类 Application、Activity、Fragment、View、Service、BroadcastReceiver 等等,但是您可能需要在Hilt 不支持的类中执行依赖注入,在这种情况下可以使用 @EntryPoint 注解进行创建,Hilt 会提供相应的依赖。

0 个评论

要回复文章请先登录注册