前言
主要介绍hilt的整体框架,当前源码的讲解使用到案例会基于hilt demo。可自行下载。
AndroidEntryPointProcessor类处理@AndroidEntryPoint和@HiltAndroidApp注解。当前使用该注解的节点校验并且生成AndroidEntryPointMetadata对象,针对该`AndroidEntryPointMetadata对象再生成类。
校验并生成AndroidEntryPointMetadata对象
使用@AndroidEntryPoint或@HiltAndroidApp注解修饰的节点规则校验,校验过程中生成AndroidEntryPointMetadata对象。
校验规则
-
节点使用@HiltAndroidApp或@AndroidEntryPoint注解修饰有且仅有一个;
-
@HiltAndroidApp或@AndroidEntryPoint注解只能用于修饰类,而不能用于修饰接口;
-
@HiltAndroidApp或@AndroidEntryPoint注解修饰的类不能使用泛型;
-
判断 - @HiltAndroidApp或@AndroidEntryPoint注解修饰的类禁止超类验证(默认true) && @HiltAndroidApp或@AndroidEntryPoint注解的value值是Void.class类型:
-
4.1 true: @HiltAndroidApp或@AndroidEntryPoint注解修饰的类不是kotlin文件 || 如果是kotlin文件,那么该类存在不是默认参数的构造函数;
-
4.2 false:
-
① @HiltAndroidApp或@AndroidEntryPoint注解的value值不能是Void类型;
-
② @HiltAndroidApp或@AndroidEntryPoint注解修饰的类CLASS extends Hilt_CLASS;
-
@HiltAndroidApp或@AndroidEntryPoint注解的value值类型,不能是@HiltAndroidApp或@AndroidEntryPoint注解修饰的类;否则形成死循环;
-
baseElement表示@HiltAndroidApp或@AndroidEntryPoint注解的value值节点(或@HiltAndroidApp或@AndroidEntryPoint注解修饰的类的父类),如果baseElement使用了@HiltAndroidApp或@AndroidEntryPoint注解修饰:
-
(1) @HiltAndroidApp或@AndroidEntryPoint注解修饰的类 和 其baseElement节点要么都使用@WithFragmentBindings注解修饰,要么都不要使用该注解;
-
(2) @HiltAndroidApp或@AndroidEntryPoint注解修饰的类不要使用@OptionalInject修饰的注解修饰 || baseElement类型使用@OptionalInject修饰的注解修饰;
-
@HiltAndroidApp只能用于修饰Application的继承类;
-
@AndroidEntryPoint可用于修饰Activity、Service、Broadcast_service,Fragment,View:
-
(1)@AndroidEntryPoint用于修饰Activity时,只能修饰androidx.activity.ComponentActivity的继承节点;
-
(2)@AndroidEntryPoint不能用于修饰Application的继承类。
AndroidEntryPointMetadata对象属性
-
TypeElement element: @HiltAndroidApp或@AndroidEntryPoint注解修饰的类;
-
TypeElement baseElement: @HiltAndroidApp或@AndroidEntryPoint注解的value值节点或@HiltAndroidApp或@AndroidEntryPoint注解修饰的类的父类;
-
ClassName generatedClassName:@HiltAndroidApp或@AndroidEntryPoint注解修饰的类CLASS生成的类名 - Hilt_CLASS;
-
boolean requiresBytecodeInjection: 判断 - @HiltAndroidApp或@AndroidEntryPoint注解修饰的类禁止超类验证 && @HiltAndroidApp或@AndroidEntryPoint注解的value值是Void.class类型;
-
AndroidEntryPointMetadata.AndroidType androidType: Type类的androidType属性;
- 注:下面有对AndroidType对象的描述;
-
Optional baseMetadata:baseElement(或其父节点)如果使用了@HiltAndroidApp或@AndroidEntryPoint注解修饰,生成的AndroidEntryPointMetadata对象;
-
ImmutableSet installInComponents:Type类的component属性;
- 注:下面有对Type类的描述;
-
TypeName componentManager:Type类的manager属性;
-
Optional componentManagerInitArgs:Type类的componentManagerInitArgs属性;
Type
该类主要有以下四个属性:
- ClassName component;
- AndroidType androidType;
- ClassName manager;
- CodeBlock componentManagerInitArgs。
针对Application、service、broadcast_receiver、activity、fragment和view组件采用不同处理。
Application
- ClassName component:SingletonComponent接口;
- AndroidType androidType:AndroidType.APPLICATION;
- ClassName manager:ApplicationComponentManager类
- CodeBlock componentManagerInitArgs:null。
Service
- ClassName component:ServiceComponent接口;
- AndroidType androidType:AndroidType.SERVICE;
- ClassName manager:ServiceComponentManager类
- CodeBlock componentManagerInitArgs:CodeBlock.of("this")。
Broadcast_Receiver
- ClassName component:SingletonComponent接口;
- AndroidType androidType:AndroidType.BROADCAST_RECEIVER;
- ClassName manager:BroadcastReceiverComponentManager类
- CodeBlock componentManagerInitArgs:null。
Activity
- ClassName component:ActivityComponent接口;
- AndroidType androidType:AndroidType.ACTIVITY;
- ClassName manager:ActivityComponentManager类;
- CodeBlock componentManagerInitArgs:CodeBlock.of("this")。
Fragment
- ClassName component:FragmentComponent接口;
- AndroidType androidType:AndroidType.FRAGMENT;
- ClassName manager:FragmentComponentManager类;
- CodeBlock componentManagerInitArgs:CodeBlock.of("this")。
View
- ClassName component:ViewWithFragmentComponent接口;
- AndroidType androidType:AndroidType.VIEW;
- ClassName manager:ViewComponentManager类;
- CodeBlock componentManagerInitArgs:CodeBlock.of("this, true /* hasFragmentBindings */")。
View no fragment
- ClassName component:ViewComponent接口;
- AndroidType androidType:AndroidType.VIEW;
- ClassName manager:ViewComponentManager类;
- CodeBlock componentManagerInitArgs:CodeBlock.of("this, false /* hasFragmentBindings */")。
生成类
调用gnerate()方法生成不同类。
InjectorEntryPointGenerator
-
生成的类名是@HiltAndroidApp或@AndroidEntryPoint注解修饰的节点拼接:$CLASS_GeneratedInjector;
-
生成的一定是public修饰的接口:
- (1)添加注解:
@OriginatingElement(topLevelClass = @HiltAndroidApp或@AndroidEntryPoint注解修饰的节点类型.class), - (2)添加
@GeneratedEntryPoint注解, - (3)添加
@InstallIn注解; - (4)添加
@Generated("InjectorEntryPointGenerator")注解; - (5)如果@HiltAndroidApp或@AndroidEntryPoint注解修饰的节点使用了@TargetApi注解修饰,把当前@TargetApi注解拷贝过来;
- 添加
public abstract(接口不需要abstract修饰)修饰的方法:
-
(1)方法名:inject$Class - inject拼接@HiltAndroidApp或@AndroidEntryPoint注解修饰的节点(Foo.Bar.Baz -> injectFoo_Bar_Baz);
-
(2)方法参数:类型 - 当前@HiltAndroidApp或@AndroidEntryPoint注解修饰的节点类型;参数名 - 当前@HiltAndroidApp或@AndroidEntryPoint注解修饰的节点类型首字母小写
demo如下:
-
Application:
@HiltAndroidApp class Application : Application() {...}
-
MainActivity:
@AndroidEntryPoint class MainActivity : AppCompatActivity(R.layout.activity_main)
-
UserListFragment:
@AndroidEntryPoint class UserListFragment : Fragment() {...}
-
UserDetailsFragment:
@AndroidEntryPoint class UserDetailsFragment : Fragment() {...}
生成代码:
-
Application_GeneratedInjector
@Generated("InjectorEntryPointGenerator") @OriginatingElement( topLevelClass = Application.class ) @GeneratedEntryPoint @InstallIn(SingletonComponent.class) public interface Application_GeneratedInjector { void injectApplication(Application application); } -
MainActivity_GeneratedInjector
@OriginatingElement( topLevelClass = MainActivity.class ) @GeneratedEntryPoint @InstallIn(ActivityComponent.class) public interface MainActivity_GeneratedInjector { void injectMainActivity(MainActivity mainActivity); } -
UserListFragment_GeneratedInjector
@OriginatingElement( topLevelClass = UserListFragment.class ) @GeneratedEntryPoint @InstallIn(FragmentComponent.class) public interface UserListFragment_GeneratedInjector { void injectUserListFragment(UserListFragment userListFragment); } -
UserDetailsFragment_GeneratedInjector
@OriginatingElement( topLevelClass = UserDetailsFragment.class ) @GeneratedEntryPoint @InstallIn(FragmentComponent.class) public interface UserDetailsFragment_GeneratedInjector { void injectUserDetailsFragment(UserDetailsFragment userDetailsFragment); }
标签1
这里打个该篇文章的标签1下面的内容暂且不要看!!!先看下一章,这里!!!
ApplicationGenerator
@HiltAndroidApp修饰的Application实现类生成代码。
实际并没有启动当前代码生成工作!但是在最后面调用了当前类生成代码。
这里可以不看或简单理解下,后面还会介绍!!!
-
生成的是一个abstract抽象类,类名:Hilt_APP表示@HiltAndroidApp修饰的节点;
-
Hilt_$APP类继承Application;
-
如果@HiltAndroidApp修饰的节点是kotlin文件,那么当前 Hilt_$APP抽象类使用public修饰;
-
添加
private final修饰的变量:private final ApplicationComponentManager componentManager =xxx; -
添加继承方法
componentManager; -
Hilt_$APP类添加注释:
A generated base class to be extended by the @HiltAndroidApp annotated class. If using the Gradle plugin, this is swapped as the base class via bytecode transformation. -
添加注解:
@Generated("ApplicationGenerator"); -
baseElement如果存在泛型, 该泛型添加到Hilt_$APP类上;
-
如果@HiltAndroidApp修饰的节点使用了TargetApi注解,拷贝到Hilt_$APP类上;
-
继承GeneratedComponentManagerHolder接口,并且实现generatedComponent方法(在当前element生成的AndroidEntryPointMetadata对象的baseMetadata不存在的情况下才会继承并且生成方法):
-
实现继承方法
onCreate,添加@CallSuper注解;
生成的代码如下:
//A generated base class to be extended by the @HiltAndroidApp annotated class. If using the Gradle plugin, this is swapped as the base class via bytecode transformation.
@Generated("ApplicationGenerator")
abstract class Hilt_Application extends Application implements GeneratedComponentManagerHolder {
private final ApplicationComponentManager componentManager =
new ApplicationComponentManager(
new ComponentSupplier() {
@Override
public Object get() {
//_com_aregyan_github_Application_HiltComponents内部类SingletonComponent生成的,该类后面生成。
return Dagger_com_aregyan_github_Application_HiltComponents_SingletonComponent.builder()
.applicationContextModule(new ApplicationContextModule(Hilt_Application.this))
.build();
}
}
);
@Override
public final ApplicationComponentManager componentManager() {
return componentManager;
}
@Override
public final Object generatedComponent() {
return this.componentManager().generatedComponent();
}
@CallSuper
@Override
public void onCreate() {
// This is a known unsafe cast, but is safe in the only correct use case:
// $APP extends Hilt_$APP
((Application_GeneratedInjector)generatedComponent()).injectApplication((Application) this);
super.onCreate();
}
}
ActivityGenerator
@AndroidEntryPoint修饰的Activity实现类生成代码。
业务代码比较简单,直接上生成的代码:
/**
* A generated base class to be extended by the @dagger.hilt.android.AndroidEntryPoint annotated class. If using the Gradle plugin, this is swapped as the base class via bytecode transformation.
*/
public abstract class Hilt_MainActivity extends AppCompatActivity implements GeneratedComponentManagerHolder {
private volatile ActivityComponentManager componentManager;
private final Object componentManagerLock = new Object();
private boolean injected = false;
Hilt_MainActivity() {
super();
_initHiltInternal();
}
Hilt_MainActivity(int contentLayoutId) {
super(contentLayoutId);
_initHiltInternal();
}
private void _initHiltInternal() {
addOnContextAvailableListener(new OnContextAvailableListener() {
@Override
public void onContextAvailable(Context context) {
inject();
}
});
}
@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;
}
protected void inject() {
if (!injected) {
injected = true;
((MainActivity_GeneratedInjector) this.generatedComponent()).injectMainActivity(UnsafeCasts.<MainActivity>unsafeCast(this));
}
}
@Override
public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
return DefaultViewModelFactories.getActivityFactory(this, super.getDefaultViewModelProviderFactory());
}
}
BroadcastReceiverGenerator
@AndroidEntryPoint修饰的BroadcastReceiver实现类生成代码。
生成的代码如下:
@Generated("BroadcastReceiverGenerator")
abstract class Hilt_$CLASS extends $BASE {
private volatile boolean injected = false;
private final Object injectedLock = new Object();
protected void inject(Context context) {
if (!injected) {
synchronized (injectedLock){
if (!injected){
(($CLASS_GeneratedInjector)BroadcastReceiverComponentManager.generatedComponent(context)).inject$CLASS(($CLASS) this);
}
}
injected = true;
}
}
@CallSuper
@Override
public void onReceive(Context context, Intent intent) {
inject(context);
super.onReceive(context, intent);
}
}
FragmentGenerator
AndroidEntryPoint修饰的UserListFragment实现类生成代码如下:
/**
* A generated base class to be extended by the @dagger.hilt.android.AndroidEntryPoint annotated class. If using the Gradle plugin, this is swapped as the base class via bytecode transformation.
*/
public abstract class Hilt_UserListFragment extends Fragment implements GeneratedComponentManagerHolder {
private ContextWrapper componentContext;
private boolean disableGetContextFix;
private volatile FragmentComponentManager componentManager;
private final Object componentManagerLock = new Object();
private boolean injected = false;
Hilt_UserListFragment() {
super();
}
Hilt_UserListFragment(int contentLayoutId) {
super(contentLayoutId);
}
@Override
@CallSuper
public void onAttach(Context context) {
super.onAttach(context);
initializeComponentContext();
inject();
}
@Override
@SuppressWarnings("deprecation")
@CallSuper
@MainThread
public void onAttach(Activity activity) {
super.onAttach(activity);
Preconditions.checkState(componentContext == null || FragmentComponentManager.findActivity(componentContext) == activity, "onAttach called multiple times with different Context! Hilt Fragments should not be retained.");
initializeComponentContext();
inject();
}
private void initializeComponentContext() {
if (componentContext == null) {
// Note: The LayoutInflater provided by this componentContext may be different from super Fragment's because we getting it from base context instead of cloning from the super Fragment's LayoutInflater.
componentContext = FragmentComponentManager.createContextWrapper(super.getContext(), this);
disableGetContextFix = FragmentGetContextFix.isFragmentGetContextFixDisabled(super.getContext());
}
}
@Override
public Context getContext() {
if (super.getContext() == null && !disableGetContextFix) {
return null;
}
initializeComponentContext();
return componentContext;
}
@Override
public LayoutInflater onGetLayoutInflater(Bundle savedInstanceState) {
LayoutInflater inflater = super.onGetLayoutInflater(savedInstanceState);
return LayoutInflater.from(FragmentComponentManager.createContextWrapper(inflater, this));
}
@Override
public final Object generatedComponent() {
return this.componentManager().generatedComponent();
}
protected FragmentComponentManager createComponentManager() {
return new FragmentComponentManager(this);
}
@Override
public final FragmentComponentManager componentManager() {
if (componentManager == null) {
synchronized (componentManagerLock) {
if (componentManager == null) {
componentManager = createComponentManager();
}
}
}
return componentManager;
}
protected void inject() {
if (!injected) {
injected = true;
((UserListFragment_GeneratedInjector) this.generatedComponent()).injectUserListFragment(UnsafeCasts.<UserListFragment>unsafeCast(this));
}
}
@Override
public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
return DefaultViewModelFactories.getFragmentFactory(this, super.getDefaultViewModelProviderFactory());
}
}
ServiceGenerator
AndroidEntryPoint修饰的Service实现类生成代码如下:
//A generated base class to be extended by the @AndroidEntryPoint annotated class. If using the Gradle plugin, this is swapped as the base class via bytecode transformation.
@Generated("ServiceGenerator")
abstract class Hilt_$CLASS extends $BASE {
private boolean injected = false;
protected void inject() {
if (!injected) {
generatedComponent().inject$CLASS(($CLASS) this);
injected = true;
}
}
private final Object componentManagerLock = new Object();
private volatile ServiceComponentManager componentManager;
protected ServiceComponentManager createComponentManager() {
return new ServiceComponentManager(this);
}
@Override
public ServiceComponentManager componentManager() {
if (componentManager == null) {
synchronize (componentManagerLock) {
if (componentManager == null) {
componentManager = createComponentManager();
}
}
}
return componentManager;
}
@CallSuper
@Override
public void onCreate() {
inject();
super.onCreate();
}
@Override
public final Object generatedComponent() {
return this.componentManager().generatedComponent();
}
}
ViewGenerator
AndroidEntryPoint修饰的View实现类生成代码如下:
//A generated base class to be extended by the @AndroidEntryPoint annotated class. If using the Gradle plugin, this is swapped as the base class via bytecode transformation.
@Generated("ViewGenerator")
abstract class Hilt_$CLASS extends $BASE implements GeneratedComponentManagerHolder {
private boolean injected;
protected void inject() {
if (!injected) {
(($CLASS_GeneratedInjector)this.generatedComponent()).inject$CLASS(($CLASS) this);
injected = true;
}
}
private volatile ViewComponentManager componentManager;
protected ViewComponentManager createComponentManager() {
return new ViewComponentManager(this,true);
}
@Override
public ViewComponentManager componentManager() {
componentManager = createComponentManager();
return componentManager;
}
@Override
public final Object generatedComponent() {
return this.componentManager().generatedComponent();
}
}
总结
首先生成xx_GeneratedInjector类,该类的作用是表示容器中的注解实例化后注入当前xx类;
然后在生成Hilt_xx类,该类的作用是还是为了完成注入,等待下一步处理。