0.基于Dager2.38.1的hilt源码-前言

240 阅读4分钟

前言

想了解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地址,可自行查看

  1. 在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() {...}
    
  2. viemodel上使用了@HiltViewModel修饰:

     @HiltViewModel
     class UserListViewModel @Inject constructor(
         private val userListRepository: UserListRepository
     ) : ViewModel() {...}
    
     @HiltViewModel
     class UserDetailsViewModel @Inject constructor(
         private val userDetailsRepository: UserDetailsRepository
     ) : ViewModel() {...}
    
  3. 这样操作就可以使用和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节点

源码不是如下代码,这里是方便我们理解我这边单方面做的改动!!!后面代码如果看不懂,完全可以按照当下代码去理解。这里的代码对我们的理解非常非常非常重要!!!

请务必认真理解!!!

  1. 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();
     	}
     }
    
  • 以上代码应该很好理解吧。
  1. 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类;

  1. 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修饰的方法返回类型;

  1. 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();
     	}
     }
    
  2. 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相关源码的理解。