开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 13 天,点击查看活动详情
其实hilt的使用在Android比较简单,在android上面有和android组件相关的几个component以及相应是scope。还有另外一个好处就是我们不需要自己再去主动做注入了,一切由hilt自己来完成。
hilt的底层最终还是靠dagger完成的,我也比较好奇hilt是怎么和android的组件去做注入的,今天我们先看看activity是如何注入的。
我们以上一讲的例子为例开始讲,看看activity的代码:
@AndroidEntryPoint
class HiltExampleActivity : AppCompatActivity() {
@Inject
lateinit var myFamily: MyFamily
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_hilt_example)
Log.i("hiltExample","my family:${myFamily.familyMember()}")
}
}
这里我们在activity中注入了一个MyFamily的类,类的内容很简单:
class MyFamily @Inject constructor(){
fun familyMember():List<String>{
return listOf("sophie","leo","catherine","amy")
}
}
这个类只是普通类,所以就直接注入就好了。
首先看生成的hilt activity的名字:Hilt_HiltExampleActivity,也就是在原来名字前面加了:Hilt_xx
@Override
public final Object generatedComponent() {
return this.componentManager().generatedComponent();
}
protected ActivityComponentManager createComponentManager() {
return new ActivityComponentManager(this);
}
@Override
public final ActivityComponentManager componentManager() {
if (componentManager == null) {
synchronized (componentManagerLock) {
if (componentManager == null) {
componentManager = createComponentManager();
}
}
}
return componentManager;
}
再看着三个方法,这三个方法主要是产生component的,比我们自己创建component来说它是线程安全的,先生成了一个ActivityComponentManager,再根据ActivityComponentManager生成相应的component。
Hilt_HiltExampleActivity(int contentLayoutId) {
super(contentLayoutId);
_initHiltInternal();
}
private void _initHiltInternal() {
addOnContextAvailableListener(new OnContextAvailableListener() {
@Override
public void onContextAvailable(Context context) {
inject();
}
});
}
再看看这两个方法,一个是acitivity的构造,另外一个就是注入实例的时机了。
public final void addOnContextAvailableListener(
@NonNull OnContextAvailableListener listener) {
mContextAwareHelper.addOnContextAvailableListener(listener);
}
看这个应该是在监听context Available的时机了,但是这个context available的时机又是什么呢,其实你找相应的源码就可以发现,这个其实就在acitivity的oncreate方法里面:
protected void onCreate(@Nullable Bundle savedInstanceState) {
// Restore the Saved State first so that it is available to
// OnContextAvailableListener instances
mSavedStateRegistryController.performRestore(savedInstanceState);
mContextAwareHelper.dispatchOnContextAvailable(this);
super.onCreate(savedInstanceState);
ReportFragment.injectIfNeededIn(this);
if (BuildCompat.isAtLeastT()) {
mOnBackPressedDispatcher.setOnBackInvokedDispatcher(
Api33Impl.getOnBackInvokedDispatcher(this)
);
}
if (mContentLayoutId != 0) {
setContentView(mContentLayoutId);
}
}
dispatchOnContextAvailable方法就是在分发inject的事件。我们再返回到上面,看看inject都干了什么:
protected void inject() {
if (!injected) {
injected = true;
((HiltExampleActivity_GeneratedInjector) this.generatedComponent()).injectHiltExampleActivity(UnsafeCasts.<HiltExampleActivity>unsafeCast(this));
}
}
这个里面其实就在做一系列的注入工作了。
@OriginatingElement(
topLevelClass = HiltExampleActivity.class
)
@GeneratedEntryPoint
@InstallIn(ActivityComponent.class)
public interface HiltExampleActivity_GeneratedInjector {
void injectHiltExampleActivity(HiltExampleActivity hiltExampleActivity);
}
这个就是那个最终的AcitivityComponent,虽然和dagger里面的component不是很一样,但是功能是一样的了。
除了上面这些,hilt还会针对Activity中inject的成员生成相应的MembersInjector的provider类。以上面HiltExampleActivity注入的MyFamily为例:
public final class HiltExampleActivity_MembersInjector implements MembersInjector<HiltExampleActivity> {
private final Provider<MyFamily> myFamilyProvider;
public HiltExampleActivity_MembersInjector(Provider<MyFamily> myFamilyProvider) {
this.myFamilyProvider = myFamilyProvider;
}
public static MembersInjector<HiltExampleActivity> create(Provider<MyFamily> myFamilyProvider) {
return new HiltExampleActivity_MembersInjector(myFamilyProvider);
}
@Override
public void injectMembers(HiltExampleActivity instance) {
injectMyFamily(instance, myFamilyProvider.get());
}
@InjectedFieldSignature("com.laworks.dagger2example.HiltExampleActivity.myFamily")
public static void injectMyFamily(HiltExampleActivity instance, MyFamily myFamily) {
instance.myFamily = myFamily;
}
}
首先是在构造方法里面生成provider类,然后在调用injectMyFamily方法将myFamily实例赋值给HiltExampleActivity类里面。成员的依赖注入就完成了。
需要注意一点的是,在高版本的hilt里面已经不需要依赖:
androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03
依赖这个包会一直报错,告诉你找不到相应的DefaultActivityViewModelFactory。
对于dagger的module和hilt的module如果需要混合使用,那么需要在build.gradle加上一个配置:
tasks.withType(JavaCompile) {
configure(options) {
options.compilerArgs << "-Adagger.hilt.disableModulesHaveInstallInCheck=true"
}
}
然后在不需要hilt注入的module里面加上:
@DisableInstallInCheck
这样就可以使用dagger的module了。