HiltSource

Hilt Usage

  1. Annotate the Application class with @HiltAndroidApp
  2. Annotate the Activity class with @AndroidEntryPoint
  3. Annotate the ViewModel class with @HiltViewModel and @Inject constructor
  4. Annotate the Repository class with @Singleton and @Inject constructor

ViewModel注入过程

以LoginActivity为例

@HiltViewModel
class LoginViewModel @Inject constructor(
    application: Application,
    private val savedStateHandle: SavedStateHandle,
    private val userRepository: UserRepository
) :
LoginViewModel by viewModels()

@MainThread
inline fun <reified VM : ViewModel> ComponentActivity.viewModels(
    noinline factoryProducer: (() -> Factory)? = null
): Lazy<VM> {
    val factoryPromise = factoryProducer ?: {
        defaultViewModelProviderFactory//main
    }

    return ViewModelLazy(VM::class, { viewModelStore }, factoryPromise)
}
class ViewModelLazy<VM : ViewModel> (
    private val viewModelClass: KClass<VM>,
    private val storeProducer: () -> ViewModelStore,
    private val factoryProducer: () -> ViewModelProvider.Factory
) : Lazy<VM> {
    private var cached: VM? = null

    override val value: VM
        get() {
            val viewModel = cached
            return if (viewModel == null) {
                val factory = factoryProducer()
                val store = storeProducer()
                //main
                ViewModelProvider(store, factory).get(viewModelClass.java).also {
                    cached = it
                }
            } else {
                viewModel
            }
        }

factoryProducer()

Hilt_LoginActivity插入继承结构作为原本LoginActivity的父类

build/generated/source/kapt/debug/com/xh/demo/androidx/arch/login/Hilt_LoginActivity.java

public abstract class Hilt_LoginActivity<T extends ViewDataBinding> extends DataBindingActivity<T> implements GeneratedComponentManagerHolder {
  @Override
  public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
    return DefaultViewModelFactories.getActivityFactory(this);
  }
}

DefaultViewModelFactories.getActivityFactory

public final class DefaultViewModelFactories {
 public static ViewModelProvider.Factory getActivityFactory(ComponentActivity activity) {
    return EntryPoints.get(activity, ActivityEntryPoint.class)
        .getHiltInternalFactoryFactory()
        .fromActivity(activity);
  }
    ViewModelProvider.Factory fromActivity(ComponentActivity activity) {
      return getHiltViewModelFactory(activity,
          activity.getIntent() != null ? activity.getIntent().getExtras() : null,
          defaultActivityFactory);
    }
  
    private ViewModelProvider.Factory getHiltViewModelFactory(
        SavedStateRegistryOwner owner,
        @Nullable Bundle defaultArgs,
        @Nullable ViewModelProvider.Factory extensionDelegate) {
      ViewModelProvider.Factory delegate = extensionDelegate == null
          ? new SavedStateViewModelFactory(application, owner, defaultArgs)
          : extensionDelegate;
      return new HiltViewModelFactory(//main
          owner, defaultArgs, keySet, delegate, viewModelComponentBuilder);
    }
}

ViewModelProvider.get

@NonNull
@MainThread
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
   viewModel = mFactory.create(modelClass);
}

HiltViewModelFactory

public HiltViewModelFactory(
    @NonNull SavedStateRegistryOwner owner,
    @Nullable Bundle defaultArgs,
    @NonNull Set<String> hiltViewModelKeys,
    @NonNull ViewModelProvider.Factory delegateFactory,
    @NonNull ViewModelComponentBuilder viewModelComponentBuilder) {
  this.hiltViewModelKeys = hiltViewModelKeys;
  this.delegateFactory = delegateFactory;
  this.hiltViewModelFactory =
      new AbstractSavedStateViewModelFactory(owner, defaultArgs) {
        @NonNull
        @Override
        @SuppressWarnings("unchecked")
        protected <T extends ViewModel> T create(
            @NonNull String key, @NonNull Class<T> modelClass, @NonNull SavedStateHandle handle) {//main
          ViewModelComponent component = viewModelComponentBuilder.savedStateHandle(handle).build();
          Provider<? extends ViewModel> provider =
              EntryPoints.get(component, ViewModelFactoriesEntryPoint.class)
                  .getHiltViewModelMap()
                  .get(modelClass.getName());
          if (provider == null) {
            throw new IllegalStateException(
                "Expected the @HiltViewModel-annotated class '" + modelClass.getName() 
                    + "' to be available in the multi-binding of "
                    + "@HiltViewModelMap but none was found.");
          }
          return (T) provider.get();
        }
      };
}
/**
 * View Model Provider Factory for the Hilt Extension.
 *
 * <p>A provider for this factory will be installed in the {@link
 * dagger.hilt.android.components.ActivityComponent} and {@link
 * dagger.hilt.android.components.FragmentComponent}. An instance of this factory will also be the
 * default factory by activities and fragments annotated with {@link
 * dagger.hilt.android.AndroidEntryPoint}.
 */
public final class HiltViewModelFactory implements ViewModelProvider.Factory {
  
  @NonNull
  @Override
  public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
    if (hiltViewModelKeys.contains(modelClass.getName())) {
      return hiltViewModelFactory.create(modelClass);//main
    } else {
      return delegateFactory.create(modelClass);
    }
  }

ViewModelCImpl

上述provider.get()实例为:ViewModelCImpl

build/generated/source/kapt/debug/com/xh/demo/androidx/DaggerArchApplication_HiltComponents_SingletonC.java

private final class ViewModelCImpl extends ArchApplication_HiltComponents.ViewModelC {
       private LoginViewModel loginViewModel() {
        return new LoginViewModel(ApplicationContextModule_ProvideApplicationFactory.provideApplication(DaggerArchApplication_HiltComponents_SingletonC.this.applicationContextModule), savedStateHandle, DaggerArchApplication_HiltComponents_SingletonC.this.userRepository());
      } 
}

DaggerArchApplication_HiltComponents_SingletonC

build/generated/source/kapt/debug/com/xh/demo/androidx/DaggerArchApplication_HiltComponents_SingletonC.java

public final class DaggerArchApplication_HiltComponents_SingletonC extends ArchApplication_HiltComponents.SingletonC {
private UserRepository userRepository() {
  Object local = userRepository;
  if (local instanceof MemoizedSentinel) {
    synchronized (local) {
      local = userRepository;
      if (local instanceof MemoizedSentinel) {
        local = new UserRepository();
        userRepository = DoubleCheck.reentrantCheck(userRepository, local);
      }
    }
  }
  return (UserRepository) local;
}

Hilt_ArchApplication

build/generated/source/kapt/debug/com/xh/demo/androidx/Hilt_ArchApplication.java

/**
 * A generated base class to be extended by the @dagger.hilt.android.HiltAndroidApp annotated class. If using the Gradle plugin, this is swapped as the base class via bytecode transformation.
 */
public abstract class Hilt_ArchApplication extends Application implements GeneratedComponentManagerHolder {
  private final ApplicationComponentManager componentManager = new ApplicationComponentManager(new ComponentSupplier() {
    @Override
    public Object get() {
      return DaggerArchApplication_HiltComponents_SingletonC.builder()
          .applicationContextModule(new ApplicationContextModule(Hilt_ArchApplication.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:
    // ArchApplication extends Hilt_ArchApplication
    ((ArchApplication_GeneratedInjector) generatedComponent()).injectArchApplication(UnsafeCasts.<ArchApplication>unsafeCast(this));
    super.onCreate();
  }
}