前言
想了解hilt源码必须对Dagger的使用有所了解,否则将会感觉说的云里雾里。
当前hilt源码在应用上相对来说比Dagger简化很多,所以使用方便。but,他还是转换成Dagger形式,所以从源码的角度来说做的比Dagger感觉还要多。代码理解起来自然不容易。
Dagger案例
先看下Dagger的案例,为下面的Hilt做一个铺垫。
@Module(subcomponents = Subcomponent1.class,Subcomponent2.class,Subcomponent3.class)
public class Module{
@Provides
@Singleton
public A bindingMethod(B b){
return new A(b);
}
}
@Component(modules = Module.class)
public calss Component{
inject(MembersInjector m);
public SubcomponentX getSubcomponentX();//这个也是一个Subcomponent节点
}
public class MembersInjector{
@Inject
public C C;
}
@Singleton
public class C {
@Inject
public C(){}
}
hilt 使用Demo引发的不归路
实现声明:为了方便我们的理解,以下的代码是进过我个人简化再简化得来的案例。实际hilt源码比这个零散的多,而且理解困难的多。
hilt demo
demo地址,可自行查看
-
在Application(用户自定义,命名确实比较骚)使用@HiltAndroidApp修饰,Activity和Fragment使用@AndroidEntryPoint修饰:
@HiltAndroidApp class Application : Application() { override fun onCreate() { super.onCreate() if (BuildConfig.DEBUG) { Timber.plant(Timber.DebugTree()) } } } @AndroidEntryPoint class MainActivity : AppCompatActivity(R.layout.activity_main) @AndroidEntryPoint class UserListFragment : Fragment() {...} @AndroidEntryPoint class UserDetailsFragment : Fragment() {...} -
viemodel上使用了@HiltViewModel修饰:
@HiltViewModel class UserListViewModel @Inject constructor( private val userListRepository: UserListRepository ) : ViewModel() {...} @HiltViewModel class UserDetailsViewModel @Inject constructor( private val userDetailsRepository: UserDetailsRepository ) : ViewModel() {...} -
这样操作就可以使用和Dagger一样注解了,DatabaseModule和NetworkModule;
@InstallIn(SingletonComponent::class) @Module object DatabaseModule { @Provides @Singleton fun provideAppDatabase(@ApplicationContext appContext: Context): UsersDatabase { return Room.databaseBuilder( appContext, UsersDatabase::class.java, "Users" ).fallbackToDestructiveMigration().build() } @Provides fun provideChannelDao(usersDatabase: UsersDatabase): UsersDao { return usersDatabase.usersDao } } @Module @InstallIn(SingletonComponent::class) object NetworkModule { @Singleton @Provides fun provideOkHttpClient() = if (BuildConfig.DEBUG) { val loggingInterceptor = HttpLoggingInterceptor() loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY) OkHttpClient.Builder() .addInterceptor(loggingInterceptor) .build() } else { OkHttpClient .Builder() .build() } @Singleton @Provides fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit = Retrofit.Builder() .addConverterFactory(MoshiConverterFactory.create()) .baseUrl("https://api.github.com/") .client(okHttpClient) .build() @Provides @Singleton fun provideApiService(retrofit: Retrofit): UserListService = retrofit.create(UserListService::class.java) @Provides @Singleton fun provideUserDetailsService(retrofit: Retrofit): UserDetailsService = retrofit.create(UserDetailsService::class.java) }
是不是写法很简单,下面看看他到底是转换成什么样子的Dagger案例。看了估计得让人炸锅。
hilt转换成Dagger 案例
一.hilt源码将@HiltAndroidApp和@AndroidEntryPoint修饰的节点生成的接口
@HiltAndroidApp修饰的Application生成注入方法:
@OriginatingElement(
topLevelClass = Application.class
)
@GeneratedEntryPoint
@InstallIn(SingletonComponent.class)
public interface Application_GeneratedInjector {
void injectApplication(Application application);
}
@AndroidEntryPoint修饰的MainActivity生成注入方法:
@OriginatingElement(
topLevelClass = MainActivity.class
)
@GeneratedEntryPoint
@InstallIn(ActivityComponent.class)
public interface MainActivity_GeneratedInjector {
void injectMainActivity(MainActivity mainActivity);
}
@AndroidEntryPoint修饰的UserListFragment生成注入方法:
@OriginatingElement(
topLevelClass = UserListFragment.class
)
@GeneratedEntryPoint
@InstallIn(FragmentComponent.class)
public interface UserListFragment_GeneratedInjector {
void injectUserListFragment(UserListFragment userListFragment);
}
@AndroidEntryPoint修饰的UserDetailsFragment生成注入方法:
@OriginatingElement(
topLevelClass = UserDetailsFragment.class
)
@GeneratedEntryPoint
@InstallIn(FragmentComponent.class)
public interface UserDetailsFragment_GeneratedInjector {
void injectUserDetailsFragment(UserDetailsFragment userDetailsFragment);
}
二.hilt针对@HiltViewModel修饰的ViewModel子类的处理
@HiltViewModel修饰UserListViewModel生成代码,当前类作用看BindsModule类的binds方法:实例化UserListViewModel对象:
@OriginatingElement(
topLevelClass = UserListViewModel.class
)
public final class UserListViewModel_HiltModules {
private UserListViewModel_HiltModules() {
}
@Module
@InstallIn(ViewModelComponent.class)
public abstract static class BindsModule {
private BindsModule() {
}
@Binds
@IntoMap
@StringKey("com.aregyan.github.views.userList.UserListViewModel")
@HiltViewModelMap
public abstract ViewModel binds(UserListViewModel vm);
}
@Module
@InstallIn(ActivityRetainedComponent.class)
public static final class KeyModule {
private KeyModule() {
}
@Provides
@IntoSet
@HiltViewModelMap.KeySet
public static String provide() {
return "com.aregyan.github.views.userList.UserListViewModel";
}
}
}
@HiltViewModel修饰UserListViewModel生成代码,当前类作用看BindsModule类的binds方法:实例化UserDetailsViewModel对象:
@OriginatingElement(
topLevelClass = UserDetailsViewModel.class
)
public final class UserDetailsViewModel_HiltModules {
private UserDetailsViewModel_HiltModules() {
}
@Module
@InstallIn(ViewModelComponent.class)
public abstract static class BindsModule {
private BindsModule() {
}
@Binds
@IntoMap
@StringKey("com.aregyan.github.views.userDetails.UserDetailsViewModel")
@HiltViewModelMap
public abstract ViewModel binds(UserDetailsViewModel vm);
}
@Module
@InstallIn(ActivityRetainedComponent.class)
public static final class KeyModule {
private KeyModule() {
}
@Provides
@IntoSet
@HiltViewModelMap.KeySet
public static String provide() {
return "com.aregyan.github.views.userDetails.UserDetailsViewModel";
}
}
}
三.hilt提供的component节点
源码不是如下代码,这里是方便我们理解我这边单方面做的改动!!!后面代码如果看不懂,完全可以按照当下代码去理解。这里的代码对我们的理解非常非常非常重要!!!
请务必认真理解!!!
-
SingleTonComponent节点:
@Component(modules = [ DatabaseModule.class, NetworkModule.class, //自行去查看,比较简单的module节点 ApplicationContextModule.class ]) @Singleton public static abstract class SingletonComponent implements Application_GeneratedInjector { //Application_GeneratedInjector类中的方法 //void injectApplication(Application application); ActivityRetainedComponentBuilder retainedComponentBuilder(); @Component.Builder public static interface Builder{ Builder applicationContextModule(ApplicationContextModule context); SingletonComponent build(); } }
- 以上代码应该很好理解吧。
-
ActivityRetainedComponent类:
@subComponent(modules = [ UserDetailsViewModel_HiltModules.KeyModule.class, UserListViewModel_HiltModules.KeyModule.class, //hilt源码 ActivityRetainedComponentManager.LifecycleModule.class, ]) @ActivityRetainedScoped public static abstract class ActivityRetainedComponent{ ActivityComponentBuilder activityComponentBuilder(); ActivityRetainedLifecycle getActivityRetainedLifecycle(); @SubComponent.Builder static interface Builder implements ActivityRetainedComponentBuilder{ ActivityRetainedComponent build(); } }
-
(1)
ActivityRetainedComponentManager.LifecycleModule提供bind方法,目的在于ActivityRetainedLifecycle对象的实例化是其子类Lifecycle; -
(2)
ActivityRetainedComponent类的getActivityRetainedLifecycle实际操作的是Lifecycle类;
-
ActivityComponent类:
@subComponent(modules = [ DefaultViewModelFactories.ActivityModule.class, ActivityModule.class, ]) @ActivityScoped public static abstract class ActivityComponent implements MainActivity_GeneratedInjector { //MainActivity_GeneratedInjector中的方法 //void injectMainActivity(MainActivity mainActivity); InternalFactoryFactory getHiltInternalFactoryFactory(); @HiltViewModelMap.KeySet Set<String> getViewModelKeys(); ViewModelComponentBuilder getViewModelComponentBuilder(); FragmentComponentBuilder fragmentComponentBuilder(); @SubComponent.Builder static interface Builder implements ActivityComponentBuilder{ ActivityComponentBuilder activity( @BindsInstance Activity activity); ActivityComponent build(); } }
-
(1)实例化InternalFactoryFactory对象;
-
(2)getViewModelKeys方法收集UserListViewModel_HiltModules和UserDetailsViewModel_HiltModules中@HiltViewModelMap.KeySet修饰的方法返回类型;
-
FragmentComponent类:
@subComponent @FragmentScoped public static abstract class FragmentComponent implements UserDetailsFragment_GeneratedInjector, UserListFragment_GeneratedInjector { //UserDetailsFragment_GeneratedInjector //void injectUserDetailsFragment(UserDetailsFragment userDetailsFragment); //UserListFragment_GeneratedInjector //void injectUserListFragment(UserListFragment userListFragment); InternalFactoryFactory getHiltInternalFactoryFactory(); @SubComponent.Builder static interface Builder implements FragmentComponentBuilder{ FragmentComponentBuilder fragment(@BindsInstance Fragment fragment); FragmentComponent build(); } } -
ViewModelComponent类:
@subComponent(modules = [ UserDetailsViewModel_HiltModules.BindsModule.class, UserListViewModel_HiltModules.BindsModule.class, HiltViewModelFactory.ViewModelModule.class ]) @ViewModelScoped public static abstract class ViewModelComponent implements { //HiltViewModelFactory.ViewModelFactoriesEntryPoint @HiltViewModelMap Map<String, Provider<ViewModel>> getHiltViewModelMap() @SubComponent.Builder static interface Builder implements ViewModelComponentBuilder{ ViewModelComponentBuilder savedStateHandle(@BindsInstance SavedStateHandle handle); ViewModelComponent build(); } }
总结
我也知道这个是MVVM模式,但是我目前为止还没有针对该模式进行源码层面的研究,所以没有按照套路去理解,仅仅是hilt代码沉默的。
看的比较憋屈!!!总有一种拳头打到棉花上的感觉。这个理解完,在对hilt实际应用理解一下,就针对aac相关源码的理解。