1、Hilt的介绍
Hilt是jetpack里的一个组件、是对Dagger2的二次封装,让使用的时候变的更简单、方便。在Hilt源码中大部分的代码都是Dagger2的代码。
2、Hilt的简单使用
和Dagger2一样,我们先来实现注入一个Dog对象
(1)引入Gradle依赖和插件
和 Dagger2不同的是,除了要引入API支撑以及注解处理器支持之外,Hilt还要引入Gradle插件。可以猜想到Hilt要使用Gradle插件在构建的时候做相应的操作(比如:字节码插桩)
// hilt 依赖导入
implementation "com.google.dagger:hilt-android:2.28-alpha" // hilt的支持 百分之八十的代码是来自Dagger2
annotationProcessor "com.google.dagger:hilt-android-compiler:2.28-alpha" // Dagger的注解处理器APT 依赖使用
// 导入gradle-plugin 字节码插庄
classpath 'com.google.dagger:hilt-android-gradle-plugin:2.28-alpha'
// 导入gradle-plugin 字节码插庄
id 'dagger.hilt.android.plugin' // gradle-plugin
(2)注入一个Dog对象
- 创建Dog实体类
package com.it.hilt.bean;
public class Dog {
}
- Application中使用注解
//hilt 基本上都要 用 Application来辅助
@HiltAndroidApp
public class MyAplication extends Application {
}
- 对象包裹和提供
@InstallIn(ActivityComponent.class)//注入到Activity
@Module
public class DogModule {
@Provides
public Dog provideDog() {
return new Dog();
}
}
- 注入到目标Activity
@AndroidEntryPoint
public class MainActivity extends AppCompatActivity {
private final String TAG = getClass().getSimpleName();
@Inject
public Dog dog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e(TAG, "onCreate: "+dog.hashCode() );
}
}
MainActivity: onCreate: 75412883
和Dagger不同的是Hilt减少了Companent部分、并且Hilt只能将对象注入到四大组件或者Application中。
在DogModule 中我们看到InstallIn注解,代表要注入到的目标类型,ActivityComponent表示注入到Activity,当然还有ApplicationComponent、ServiceComponent、FragmentComponent等等。
(3)注入接口的实现
- 创建一个接口和实现类
/**
* 接口
*/
public interface ITest {
/**
* 测试方法
*/
void testMethod();
}
/**
* 接口实现类
*/
public class TestImpl implements ITest {
private final String TAG = getClass().getSimpleName();
@Inject
TestImpl() {
}
@Override
public void testMethod() {
Log.e(TAG, "testMethod: hello" );
}
}
- 创建Module
@Module
@InstallIn(ActivityComponent.class)//注入到Activity
public abstract class TestInterfaceModule {
@Binds
public abstract ITest binderTestClass(TestImpl test);
}
- 注入到目标Activity
@AndroidEntryPoint
public class MainActivity extends AppCompatActivity {
private final String TAG = getClass().getSimpleName();
@Inject
public ITest test;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
test.testMethod();
}
}
TestImpl: testMethod: hello
3、Hilt实现的简单分析
和Dagger2的使用区别我们发现、Hilt少了Companent类以及不需要在初始化的时候调用inject方法。
事实真的如此吗?
我们来观察Hilt字节码插桩之后的代码
- MainActivity类
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.it.hilt;
import android.os.Bundle;
import android.util.Log;
import com.it.hilt.bean.Dog;
import dagger.hilt.android.AndroidEntryPoint;
import javax.inject.Inject;
@AndroidEntryPoint
public class MainActivity extends Hilt_MainActivity {
private final String TAG = this.getClass().getSimpleName();
@Inject
public Dog dog;
@Inject
public ITest test;
public MainActivity() {
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(2131427356);
Log.e(this.TAG, "onCreate: " + this.dog.hashCode());
this.test.testMethod();
}
}
我们发现我们自己写的MainActivity继承类被改成了Hilt_MainActivity ,再来观察Hilt_MainActivity
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.it.hilt;
import android.os.Bundle;
import androidx.annotation.CallSuper;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProvider.Factory;
import dagger.hilt.android.internal.lifecycle.DefaultViewModelFactories;
import dagger.hilt.android.internal.managers.ActivityComponentManager;
import dagger.hilt.internal.GeneratedComponentManager;
import dagger.hilt.internal.UnsafeCasts;
abstract class Hilt_MainActivity extends AppCompatActivity implements GeneratedComponentManager<Object> {
private volatile ActivityComponentManager componentManager;
private final Object componentManagerLock = new Object();
Hilt_MainActivity() {
}
Hilt_MainActivity(int contentLayoutId) {
super(contentLayoutId);
}
@CallSuper
protected void onCreate(@Nullable Bundle savedInstanceState) {
this.inject();
super.onCreate(savedInstanceState);
}
public final Object generatedComponent() {
return this.componentManager().generatedComponent();
}
protected ActivityComponentManager createComponentManager() {
return new ActivityComponentManager(this);
}
protected final ActivityComponentManager componentManager() {
if (this.componentManager == null) {
synchronized(this.componentManagerLock) {
if (this.componentManager == null) {
this.componentManager = this.createComponentManager();
}
}
}
return this.componentManager;
}
protected void inject() {
((MainActivity_GeneratedInjector)this.generatedComponent()).injectMainActivity((MainActivity)UnsafeCasts.unsafeCast(this));
}
public Factory getDefaultViewModelProviderFactory() {
Factory factory = DefaultViewModelFactories.getActivityFactory(this);
return factory != null ? factory : super.getDefaultViewModelProviderFactory();
}
}
可以看到MainActivity的onCreate方法调用了super.onCreate,因此会触发Hilt_MainActivity 的onCreate方法,而在Hilt_MainActivity 的onCreate方法中调用了inject方法,所以inject方法是Hilt帮我们调用了。来看看inject方法
protected void inject() {
((MainActivity_GeneratedInjector)this.generatedComponent()).injectMainActivity((MainActivity)UnsafeCasts.unsafeCast(this));
}
调用generatedComponent方法,生成了一个MainActivity_GeneratedInjector对象、再调用injectMainActivity方法,传入当前MainActity的实例。
private MainActivity injectMainActivity2(MainActivity instance) {
MainActivity_MembersInjector.injectDog(instance, DogModule_ProvideDogFactory.provideDog(dogModule));
MainActivity_MembersInjector.injectTest(instance, new TestImpl());
return instance;
}
@InjectedFieldSignature("com.it.hilt.MainActivity.dog")
public static void injectDog(MainActivity instance, Dog dog) {
instance.dog = dog;
}
最后的代码就基本和Dagger2 差不多了,将我们DogModule提供对象的方法赋值给传入的MainActivity的Dog变量。
小结
Hilt是对Dagger2的二次封装、Dagger2是通过APT技术生成相应的代码将对象注入到指定的目标中。由于Dagger2的使用过于繁杂,Hilt在Dagger2的基础上进行二次封装,使用APT生成代码的同时,还使用了字节码插桩的方式,将被注入的类的继承关系修改,继承了Hilt生成的类,在这个生成的类中调用inject方法。
网友评论