1.基于Dagger2.38.1的hilt源码-AndroidEntryPointProcessor

218 阅读5分钟

前言

主要介绍hilt的整体框架,当前源码的讲解使用到案例会基于hilt demo。可自行下载。

AndroidEntryPointProcessor类处理@AndroidEntryPoint和@HiltAndroidApp注解。当前使用该注解的节点校验并且生成AndroidEntryPointMetadata对象,针对该`AndroidEntryPointMetadata对象再生成类。

校验并生成AndroidEntryPointMetadata对象

使用@AndroidEntryPoint或@HiltAndroidApp注解修饰的节点规则校验,校验过程中生成AndroidEntryPointMetadata对象。

校验规则

  1. 节点使用@HiltAndroidApp或@AndroidEntryPoint注解修饰有且仅有一个;

  2. @HiltAndroidApp或@AndroidEntryPoint注解只能用于修饰类,而不能用于修饰接口;

  3. @HiltAndroidApp或@AndroidEntryPoint注解修饰的类不能使用泛型;

  4. 判断 - @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;

  1. @HiltAndroidApp或@AndroidEntryPoint注解的value值类型,不能是@HiltAndroidApp或@AndroidEntryPoint注解修饰的类;否则形成死循环;

  2. baseElement表示@HiltAndroidApp或@AndroidEntryPoint注解的value值节点(或@HiltAndroidApp或@AndroidEntryPoint注解修饰的类的父类),如果baseElement使用了@HiltAndroidApp或@AndroidEntryPoint注解修饰:

  • (1) @HiltAndroidApp或@AndroidEntryPoint注解修饰的类 和 其baseElement节点要么都使用@WithFragmentBindings注解修饰,要么都不要使用该注解;

  • (2) @HiltAndroidApp或@AndroidEntryPoint注解修饰的类不要使用@OptionalInject修饰的注解修饰 || baseElement类型使用@OptionalInject修饰的注解修饰;

  1. @HiltAndroidApp只能用于修饰Application的继承类;

  2. @AndroidEntryPoint可用于修饰Activity、Service、Broadcast_service,Fragment,View:

  • (1)@AndroidEntryPoint用于修饰Activity时,只能修饰androidx.activity.ComponentActivity的继承节点;

  • (2)@AndroidEntryPoint不能用于修饰Application的继承类。

AndroidEntryPointMetadata对象属性

  1. TypeElement element: @HiltAndroidApp或@AndroidEntryPoint注解修饰的类;

  2. TypeElement baseElement: @HiltAndroidApp或@AndroidEntryPoint注解的value值节点或@HiltAndroidApp或@AndroidEntryPoint注解修饰的类的父类;

  3. ClassName generatedClassName:@HiltAndroidApp或@AndroidEntryPoint注解修饰的类CLASS生成的类名 - Hilt_CLASS;

  4. boolean requiresBytecodeInjection: 判断 - @HiltAndroidApp或@AndroidEntryPoint注解修饰的类禁止超类验证 && @HiltAndroidApp或@AndroidEntryPoint注解的value值是Void.class类型;

  5. AndroidEntryPointMetadata.AndroidType androidType: Type类的androidType属性;

  • 注:下面有对AndroidType对象的描述;
  1. Optional baseMetadata:baseElement(或其父节点)如果使用了@HiltAndroidApp或@AndroidEntryPoint注解修饰,生成的AndroidEntryPointMetadata对象;

  2. ImmutableSet installInComponents:Type类的component属性;

  • 注:下面有对Type类的描述;
  1. TypeName componentManager:Type类的manager属性;

  2. Optional componentManagerInitArgs:Type类的componentManagerInitArgs属性;

Type

该类主要有以下四个属性:

  1. ClassName component;
  2. AndroidType androidType;
  3. ClassName manager;
  4. CodeBlock componentManagerInitArgs。

针对Application、service、broadcast_receiver、activity、fragment和view组件采用不同处理。

Application

  1. ClassName component:SingletonComponent接口;
  2. AndroidType androidType:AndroidType.APPLICATION;
  3. ClassName manager:ApplicationComponentManager类
  4. CodeBlock componentManagerInitArgs:null。

Service

  1. ClassName component:ServiceComponent接口;
  2. AndroidType androidType:AndroidType.SERVICE;
  3. ClassName manager:ServiceComponentManager类
  4. CodeBlock componentManagerInitArgs:CodeBlock.of("this")。

Broadcast_Receiver

  1. ClassName component:SingletonComponent接口;
  2. AndroidType androidType:AndroidType.BROADCAST_RECEIVER;
  3. ClassName manager:BroadcastReceiverComponentManager类
  4. CodeBlock componentManagerInitArgs:null。

Activity

  1. ClassName component:ActivityComponent接口;
  2. AndroidType androidType:AndroidType.ACTIVITY;
  3. ClassName manager:ActivityComponentManager类;
  4. CodeBlock componentManagerInitArgs:CodeBlock.of("this")。

Fragment

  1. ClassName component:FragmentComponent接口;
  2. AndroidType androidType:AndroidType.FRAGMENT;
  3. ClassName manager:FragmentComponentManager类;
  4. CodeBlock componentManagerInitArgs:CodeBlock.of("this")。

View

  1. ClassName component:ViewWithFragmentComponent接口;
  2. AndroidType androidType:AndroidType.VIEW;
  3. ClassName manager:ViewComponentManager类;
  4. CodeBlock componentManagerInitArgs:CodeBlock.of("this, true /* hasFragmentBindings */")。

View no fragment

  1. ClassName component:ViewComponent接口;
  2. AndroidType androidType:AndroidType.VIEW;
  3. ClassName manager:ViewComponentManager类;
  4. CodeBlock componentManagerInitArgs:CodeBlock.of("this, false /* hasFragmentBindings */")。

生成类

调用gnerate()方法生成不同类。

InjectorEntryPointGenerator

  1. 生成的类名是@HiltAndroidApp或@AndroidEntryPoint注解修饰的节点拼接:$CLASS_GeneratedInjector;

  2. 生成的一定是public修饰的接口:

  • (1)添加注解:@OriginatingElement(topLevelClass = @HiltAndroidApp或@AndroidEntryPoint注解修饰的节点类型.class),
  • (2)添加@GeneratedEntryPoint注解,
  • (3)添加@InstallIn注解;
  • (4)添加@Generated("InjectorEntryPointGenerator")注解;
  • (5)如果@HiltAndroidApp或@AndroidEntryPoint注解修饰的节点使用了@TargetApi注解修饰,把当前@TargetApi注解拷贝过来;
  1. 添加public abstract(接口不需要abstract修饰)修饰的方法:
  • (1)方法名:inject$Class - inject拼接@HiltAndroidApp或@AndroidEntryPoint注解修饰的节点(Foo.Bar.Baz -> injectFoo_Bar_Baz);

  • (2)方法参数:类型 - 当前@HiltAndroidApp或@AndroidEntryPoint注解修饰的节点类型;参数名 - 当前@HiltAndroidApp或@AndroidEntryPoint注解修饰的节点类型首字母小写

demo如下:

  1. Application:

    @HiltAndroidApp class Application : Application() {...}

  2. MainActivity:

    @AndroidEntryPoint class MainActivity : AppCompatActivity(R.layout.activity_main)

  3. UserListFragment:

    @AndroidEntryPoint class UserListFragment : Fragment() {...}

  4. UserDetailsFragment:

    @AndroidEntryPoint class UserDetailsFragment : Fragment() {...}

生成代码:

  1. Application_GeneratedInjector

     @Generated("InjectorEntryPointGenerator")
     @OriginatingElement(
         topLevelClass = Application.class
     )
     @GeneratedEntryPoint
     @InstallIn(SingletonComponent.class)
     public interface Application_GeneratedInjector {
       void injectApplication(Application application);
     }
    
  2. MainActivity_GeneratedInjector

     @OriginatingElement(
         topLevelClass = MainActivity.class
     )
     @GeneratedEntryPoint
     @InstallIn(ActivityComponent.class)
     public interface MainActivity_GeneratedInjector {
       void injectMainActivity(MainActivity mainActivity);
     }
    
  3. UserListFragment_GeneratedInjector

     @OriginatingElement(
         topLevelClass = UserListFragment.class
     )
     @GeneratedEntryPoint
     @InstallIn(FragmentComponent.class)
     public interface UserListFragment_GeneratedInjector {
       void injectUserListFragment(UserListFragment userListFragment);
     }
    
  4. UserDetailsFragment_GeneratedInjector

     @OriginatingElement(
         topLevelClass = UserDetailsFragment.class
     )
     @GeneratedEntryPoint
     @InstallIn(FragmentComponent.class)
     public interface UserDetailsFragment_GeneratedInjector {
       void injectUserDetailsFragment(UserDetailsFragment userDetailsFragment);
     }
    

标签1

这里打个该篇文章的标签1下面的内容暂且不要看!!!先看下一章,这里!!!

ApplicationGenerator

@HiltAndroidApp修饰的Application实现类生成代码。

实际并没有启动当前代码生成工作!但是在最后面调用了当前类生成代码。

这里可以不看或简单理解下,后面还会介绍!!!

  1. 生成的是一个abstract抽象类,类名:Hilt_APPAPP,APP表示@HiltAndroidApp修饰的节点;

  2. Hilt_$APP类继承Application;

  3. 如果@HiltAndroidApp修饰的节点是kotlin文件,那么当前 Hilt_$APP抽象类使用public修饰;

  4. 添加private final修饰的变量:private final ApplicationComponentManager componentManager =xxx;

  5. 添加继承方法componentManager;

  6. 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.

  7. 添加注解:@Generated("ApplicationGenerator")

  8. baseElement如果存在泛型, 该泛型添加到Hilt_$APP类上;

  9. 如果@HiltAndroidApp修饰的节点使用了TargetApi注解,拷贝到Hilt_$APP类上;

  10. 继承GeneratedComponentManagerHolder接口,并且实现generatedComponent方法(在当前element生成的AndroidEntryPointMetadata对象的baseMetadata不存在的情况下才会继承并且生成方法):

  11. 实现继承方法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类,该类的作用是还是为了完成注入,等待下一步处理。