Briefly describe the implementation principle of the dependency injection framework Hilt

Table of contents

in conclusion

1. Application Notes

File generated by @HiltAndroidApp annotation

Code Execution Flow

2. Object creation process

Build and look at the generated classes:

Object initialization process

ActivityCImpl starts to actually perform object creation

3. How objects in the Activity are added to life cycle management

How Component components are added to life cycle management

The addition of ViewModel is the key to giving components a life cycle


Hilt is actually a dagger, which takes over the creation of objects without endowing them with a life cycle. According to the way Hilt is used, after we use various annotations provided by Hilt to annotate Application, Activity, member variables, etc., we can call these variables immediately without caring how they were created. So when and how were these variables created? Through a simple example, analyze its approximate implementation principle according to the template code generated by Hilt.

in conclusion

The conclusion comes first, so as to have an overall concept of the framework principle:

1. Hilt will modify the source code, but there are very few changes. It will only modify the parent class type of the class in the source code. It will create a Hilt_XX class for the annotated XX class and insert it into the inheritance relationship of XX as its parent class.

2. The onCreate method of the Hilt_XX class provides the variable initialization entry, and all the annotated variables are instantiated layer by layer from here.

3. The life cycle management of components is realized through ViewModel.

Example of modifications to the source code:

package com.hdf.hilt.ui

import android.app.Application
import dagger.hilt.android.HiltAndroidApp

/**
 * Created by xiaxiao on 2021/11/16.
 *
 */
@HiltAndroidApp
class MyApplication : Application() {
}

Finally, the source code in the MyApplication.class file corresponding to the MyApplication.kt file will be modified to:

package com.hdf.hilt.ui

import android.app.Application
import dagger.hilt.android.HiltAndroidApp

/**
 * Created by xiaxiao on 2021/11/16.
 *
 */
@HiltAndroidApp
class MyApplication : Hilt_MyApplication() {
}

The Hilt_MyApplication class is generated by Hilt: class Hilt_MyApplication : Application() {}

Modifications occur in the following phases:

1. Application Notes

@HiltAndroidApp
class MyApplication : Application() {
}

Still the sample code above, as the entry of the app, is also the entry of hilt framework execution, it is necessary to add the @HiltAndroidApp annotation to MyApplication. After adding the annotations, build it, and you will find that many files have been generated:

File generated by @HiltAndroidApp annotation

Hilt_MyApplication:

As mentioned in the conclusion, a new parent class is generated, and Hilt inserts its work into the normal source code logic in this way.

public abstract class Hilt_MyApplication extends Application implements GeneratedComponentManager<Object> {
  private final ApplicationComponentManager componentManager = new ApplicationComponentManager(new ComponentSupplier() {
    @Override
    public Object get() {
      return DaggerMyApplication_HiltComponents_ApplicationC.builder()
          .applicationContextModule(new ApplicationContextModule(Hilt_MyApplication.this))
          .build();
    }
  });

  protected final ApplicationComponentManager componentManager() {
    return componentManager;
  }

  @Override
  public final Object generatedComponent() {
    return componentManager().generatedComponent();
  }

  @CallSuper
  @Override
  public void onCreate() {
    // This is a known unsafe cast, but is safe in the only correct use case:
    // MyApplication extends Hilt_MyApplication
    ((MyApplication_GeneratedInjector) generatedComponent()).injectMyApplication(UnsafeCasts.<MyApplication>unsafeCast(this));
    super.onCreate();
  }
}

The line inserted in the onCreate method is the entry point for hilt:

((MyApplication_GeneratedInjector) generatedComponent()).injectMyApplication(UnsafeCasts.unsafeCast(this));

There is a type conversion behind the code, which converts this into the source code MyApplication. In fact, it can be seen from the above comments that MyApplication actually inherits Hilt_MyApplication.

MyApplication_GeneratedInjector

From the name, it is an injector, because MyApplication is now annotated, so this class is responsible for injecting Application.

@OriginatingElement(
    topLevelClass = MyApplication.class
)
@GeneratedEntryPoint
@InstallIn(ApplicationComponent.class)
@Generated("dagger.hilt.android.processor.internal.androidentrypoint.InjectorEntryPointGenerator")
public interface MyApplication_GeneratedInjector {
  void injectMyApplication(MyApplication myApplication);
}

Similarly, it is also used as an interface, which defines the behavior, and the specific implementation needs to be instantiated elsewhere.

MyApplication_HiltComponents

There is no actual logic, but it is the most important, because the behavior of all components is defined here. Hilt declares many abstract classes and interfaces in this java file, and the work of various annotations will be based on these interfaces or abstract classes. Declare good behavior to be performed.

It declares that various XXC abstract classes will be used by the annotated Activity, Fragment, Application, etc. in the future

 For example, ActivityC is now just an empty implementation

 Let's take a look at the ApplicationC class again:

@Component(
    modules = {
        ApplicationContextModule.class,
        ActivityRetainedCBuilderModule.class,
        ServiceCBuilderModule.class
    }
)
@Singleton
public abstract static class ApplicationC implements MyApplication_GeneratedInjector,
    ApplicationComponent,
    HiltWrapper_ActivityRetainedComponentManager_LifecycleComponentBuilderEntryPoint,
    ServiceComponentManager.ServiceComponentBuilderEntryPoint,
    GeneratedComponent {
}

It can be found that ApplicationC implements the MyApplication_GeneratedInjector interface. Although it is also an abstract class, this implementation indicates that the subclasses of ApplicationC already have the function of MyApplication_GeneratedInjector. That is to say, the function of injectApplication declared by MyApplication_GeneratedInjector will definitely be implemented in the subclass of ApplicationC.

I say so much here because the relationship between these classes will appear when tracking the code logic later.

DaggerMyApplication_HiltComponents_ApplicationC

The name of this class is very long. In fact, its class name indicates that this class is a subclass of MyApplication_HiltComponents.ApplicationC, that is, the concrete implementation of the ApplicationC abstract class.

public final class DaggerMyApplication_HiltComponents_ApplicationC extends MyApplication_HiltComponents.ApplicationC {
  private DaggerMyApplication_HiltComponents_ApplicationC() {

  }

  public static Builder builder() {
    return new Builder();
  }

  public static MyApplication_HiltComponents.ApplicationC create() {
    return new Builder().build();
  }

  @Override
  public void injectMyApplication(MyApplication myApplication) {
  }

You can see that there is an implementation of the injectMyApplication method, but it is now an empty implementation.

At this point, we can roughly understand what Hilt did when the @HiltAndroidApp annotation was added to an Application:

First, a java file MyApplication_HiltComponents containing many interfaces and abstract classes will be created to standardize all class relationships and behaviors.

Then a injector MyApplication_GeneratedInjector will be created for the Application, responsible for injecting the Application.

Then create a parent class of Application, Hilt_Application, to replace the inheritance relationship of the source code, so as to insert Hilt into the normal code logic and realize the function of Hilt.

Finally, create DaggerMyApplication_HiltComponents_ApplicationC as a concrete implementation of all logic.

Code Execution Flow

Now add a line of code to MyApplication

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        Log.i("xx", javaClass.superclass.name)
    }
}

The breakpoint found that super.onCreate() entered the onCreate method of Hilt_MyApplication

public void onCreate() {
  // This is a known unsafe cast, but is safe in the only correct use case:
  // MyApplication extends Hilt_MyApplication
  ((MyApplication_GeneratedInjector) generatedComponent()).injectMyApplication(UnsafeCasts.<MyApplication>unsafeCast(this));
  super.onCreate();
}

UnsafeCasts.unsafeCast(this)

This here is actually MyApplication, so although it is an unsafe type conversion, it is no problem.

The generatedComponent finally calls the generatedComponent() method of the componentManager whose member variable is ApplicationComponentManager type. The proxy mode is used here.

Application of proxy mode:

public abstract class Hilt_MyApplication extends Application implements GeneratedComponentManager<Object> {
  private final ApplicationComponentManager componentManager = new ApplicationComponentManager(new ComponentSupplier() {
    @Override
    public Object get() {
      return DaggerMyApplication_HiltComponents_ApplicationC.builder()
          .applicationContextModule(new ApplicationContextModule(Hilt_MyApplication.this))
          .build();
    }
  });

  protected final ApplicationComponentManager componentManager() {
    return componentManager;
  }

  @Override
  public final Object generatedComponent() {
    return componentManager().generatedComponent();
  }

Hilt_MyApplication implements the GeneratedComponentManager interface, which is also implemented by ApplicationComponentManager.

The actual call is ApplicationComponentManager.generatedComponent():

public final class ApplicationComponentManager implements GeneratedComponentManager<Object> {
  private volatile Object component;
  private final Object componentLock = new Object();
  private final ComponentSupplier componentCreator;

  public ApplicationComponentManager(ComponentSupplier componentCreator) {
    this.componentCreator = componentCreator;
  }

  @Override
  public Object generatedComponent() {
    if (component == null) {
      synchronized (componentLock) {
        if (component == null) {
          component = componentCreator.get();
        }
      }
    }
    return component;
  }
}

ApplicationComponentManager.generatedComponent() uses double detection when generating components, and the real component instance is provided by a component provider ComponentSupplier, which is passed in when the component manager is created:

public abstract class Hilt_MyApplication extends Application implements GeneratedComponentManager<Object> {
  private final ApplicationComponentManager componentManager = new ApplicationComponentManager(new ComponentSupplier() {
    @Override
    public Object get() {
      return DaggerMyApplication_HiltComponents_ApplicationC.builder()
          .applicationContextModule(new ApplicationContextModule(Hilt_MyApplication.this))
          .build();
    }
  });
  。。。。

So this component is a DaggerMyApplication_HiltComponents_ApplicationC object.

Going around all the way, the injection operation of Application

((MyApplication_GeneratedInjector) generatedComponent()).injectMyApplication(UnsafeCasts.<MyApplication>unsafeCast(this));

Just call DaggerMyApplication_HiltComponents_ApplicationC.injectMyApplication(MyApplication)

@Override
public void injectMyApplication(MyApplication myApplication) {
}

In the present example, this method is implemented spatiotemporally.

So far, it is the realization principle of Hilt entrance.

2. Object creation process

Next, start adding more Hilt annotations to the example to track the specific object creation process.

Add two general classes: Doctor Doctor and Hospital where he is located

class Doctor {
    @Inject
    public Hospital hospital;
    
    @Inject
    public Doctor() {

    }
}

class Hospital {
    @Inject
    public Hospital() {
    }
}

Add a DoctorActivity:

@AndroidEntryPoint
public class DoctorActivity extends AppCompatActivity {

    @Inject
    public Doctor mDoctor;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i("xx", getClass().getSuperclass().getName());
        String s = mDoctor.hospital.toString();
        Log.i("xx", s);
    }
}

According to the function of the dependency injection framework, through the above annotations, the mDoctor variable and its internal hospital variable must have been instantiated when called.

Build and look at the generated classes:

Hospital class related:

Hospital_Factory: responsible for providing the Hospital instance, the source of this instance is new Hospital(). The Hospital_Factory itself is a singleton pattern implemented in the form of an inner class. A singleton can be guaranteed without using a synchronization lock. It can not only delay initialization, but also ensure a single instance.

Reference: In-depth understanding of singleton mode: static inner class singleton principle_mnb65482's blog-CSDN blog_Singleton mode static inner class

public final class Hospital_Factory implements Factory<Hospital> {
  @Override
  public Hospital get() {
    return newInstance();
  }

  public static Hospital_Factory create() {
    return InstanceHolder.INSTANCE;
  }

  public static Hospital newInstance() {
    return new Hospital();
  }

  private static final class InstanceHolder {
    private static final Hospital_Factory INSTANCE = new Hospital_Factory();
  }
}

Doctor related classes:

Doctor_Factory: It is different from the factory class of Hospital, because there are member variables of Hospital type in the Doctor class, so when Doctor_Factory provides a Doctor instance to the outside world, it must also ensure that the member variables in it are also instantiated, so there is an additional hospitalProvider . In addition, Doctor_Factory does not have a singleton mode, because it is impossible to assign a value to doctor.hospital.

public final class Doctor_Factory implements Factory<Doctor> {
  private final Provider<Hospital> hospitalProvider;

  public Doctor_Factory(Provider<Hospital> hospitalProvider) {
    this.hospitalProvider = hospitalProvider;
  }

  @Override
  public Doctor get() {
    Doctor instance = newInstance();
    Doctor_MembersInjector.injectHospital(instance, hospitalProvider.get());
    return instance;
  }

  public static Doctor_Factory create(Provider<Hospital> hospitalProvider) {
    return new Doctor_Factory(hospitalProvider);
  }

  public static Doctor newInstance() {
    return new Doctor();
  }
}

Doctor_MembersInjector: responsible for instantiating the variables in the Doctor.

DoctorActivity related:

Hilt_DoctorActivity: A new parent class created to insert initialization logic

DoctorActivity_GeneratedInjector: used to inject DoctorActivity

DoctorActivity_MembersInjector: Used to instantiate variables in DoctorActivity

Object initialization process

So when DoctorActivity starts, the super.onCreate() method will be executed first

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Log.i("xx", getClass().getSuperclass().getName());
    String s = mDoctor.toString();
    Log.i("xx", s);
}

Enter Hilt_DoctorActivity:

protected void onCreate(@Nullable Bundle savedInstanceState) {
  inject();
  super.onCreate(savedInstanceState);
}

All the truth begins with the inject() method.

The injection operation is very similar to Application

protected void inject() {
  ((DoctorActivity_GeneratedInjector) generatedComponent()).injectDoctorActivity(UnsafeCasts.<DoctorActivity>unsafeCast(this));
}

The core method is injectDoctorActivity() of the interface DoctorActivity_GeneratedInjector. The key is to find out the real instance of DoctorActivity_GeneratedInjector.

trace generatedComponent()

@Override
public final Object generatedComponent() {
  return componentManager().generatedComponent();
}

protected ActivityComponentManager createComponentManager() {
  return new ActivityComponentManager(this);
}

protected final ActivityComponentManager componentManager() {
  if (componentManager == null) {
    synchronized (componentManagerLock) {
      if (componentManager == null) {
        componentManager = createComponentManager();
      }
    }
  }
  return componentManager;
} 

Hilt_DoctorActivity still uses the proxy mode, and finally enters the method of the component manager ActivityComponentManager:

@Override
public Object generatedComponent() {
  if (component == null) {
    synchronized (componentLock) {
      if (component == null) {
        component = createComponent();
      }
    }
  }
  return component;
}

protected Object createComponent() {
  if (!(activity.getApplication() instanceof GeneratedComponentManager)) {
    if (Application.class.equals(activity.getApplication().getClass())) {
      throw new IllegalStateException(
          "Hilt Activity must be attached to an @HiltAndroidApp Application. "
              + "Did you forget to specify your Application's class name in your manifest's "
              + "<application />'s android:name attribute?");
    }
    throw new IllegalStateException(
        "Hilt Activity must be attached to an @AndroidEntryPoint Application. Found: "
            + activity.getApplication().getClass());
  }

  return ((ActivityComponentBuilderEntryPoint)
          activityRetainedComponentManager.generatedComponent())
      .activityComponentBuilder()
      .activity(activity)
      .build();
}

The focus is on the activityRetainedComponentManager.generatedComponent() line. From this line on, the code will take a long loop and return to DaggerMyApplication_HiltComponents_ApplicationC.

First, activityRetainedComponentManager.generatedComponent() will enter the createComponent() method of ActivityRetainedComponentManager:

private ActivityRetainedComponent createComponent() {
  return viewModelProvider.get(ActivityRetainedComponentViewModel.class).getComponent();
}

viewModelProvider is created when ActivityRetainedComponentManager is constructed:

ActivityRetainedComponentManager(ComponentActivity activity) {
  this.viewModelProvider =
      new ViewModelProvider(
          activity,
          new ViewModelProvider.Factory() {
            @NonNull
            @Override
            @SuppressWarnings("unchecked")
            public <T extends ViewModel> T create(@NonNull Class<T> aClass) {
              ActivityRetainedComponent component =
                  ((GeneratedComponentManager<LifecycleComponentBuilderEntryPoint>)
                          activity.getApplication())
                      .generatedComponent()
                      .retainedComponentBuilder()
                      .build();
              return (T) new ActivityRetainedComponentViewModel(component);
            }
          });
}

Here a ViewModelProvider.Factory instance is passed in.

The viewModelProvider.get(ActivityRetainedComponentViewModel.class) method will eventually call the create method of the Factory object passed here, so

return viewModelProvider.get(ActivityRetainedComponentViewModel.class).getComponent();

The component returned in this sentence is the ActivityRetainedComponent component created in the create method of ViewModelProvider.Factory.

Analyze this code:

ActivityRetainedComponent component =
                  ((GeneratedComponentManager<LifecycleComponentBuilderEntryPoint>)
                          activity.getApplication())
                      .generatedComponent()
                      .retainedComponentBuilder()
                      .build();

activity.getApplication() returns MyApplication, because it inherits Hilt_MyApplication, so it can be converted to (GeneratedComponentManager) type, so the generatedComponent() method to be called next is the generatedComponent() of Hilt_MyApplication:

@Override
public final Object generatedComponent() {
  return componentManager().generatedComponent();
}

What is finally returned is a DaggerMyApplication_HiltComponents_ApplicationC object. Next, enter the DaggerMyApplication_HiltComponents_ApplicationC class.

Call retainedComponentBuilder():

@Override
public ActivityRetainedComponentBuilder retainedComponentBuilder() {
  return new ActivityRetainedCBuilder();}

Call ActivityRetainedCBuilder.build():

private final class ActivityRetainedCBuilder implements MyApplication_HiltComponents.ActivityRetainedC.Builder {
  @Override
  public MyApplication_HiltComponents.ActivityRetainedC build() {
    return new ActivityRetainedCImpl();
  }
}

An ActivityRetainedCImpl object is returned, which is finally in the ActivityRetainedComponentManager class

private ActivityRetainedComponent createComponent() {
  return viewModelProvider.get(ActivityRetainedComponentViewModel.class).getComponent();
}

is returned, and then returned to the createComponent() method of the ActivityComponentManager class:

return ((ActivityComponentBuilderEntryPoint)
        activityRetainedComponentManager.generatedComponent())
    .activityComponentBuilder()
    .activity(activity)
    .build();

Continue to call the ActivityRetainedCImpl.activityComponentBuilder() method:

@Override
public ActivityComponentBuilder activityComponentBuilder() {
  return new ActivityCBuilder();}

Continue to call ActivityCBuilder.activity(activity).build():

@Override
  public ActivityCBuilder activity(Activity activity) {
    this.activity = Preconditions.checkNotNull(activity);
    return this;
  }

  @Override
  public MyApplication_HiltComponents.ActivityC build() {
    Preconditions.checkBuilderRequirement(activity, Activity.class);
    return new ActivityCImpl(activity);
  }
}

What is returned is an ActivityCImpl object.

Forgive such a big circle, in the inject method of the Hilt_DoctorActivity class:

protected void inject() {
  ((DoctorActivity_GeneratedInjector) generatedComponent()).injectDoctorActivity(UnsafeCasts.<DoctorActivity>unsafeCast(this));
}

The generatedComponent() method returns a DaggerMyApplication_HiltComponents_ApplicationC.ActivityRetainedCImpl.ActivityCImpl class instance.

At this point, the logic is finally cleared up, and it suddenly becomes clear.

ActivityCImpl starts to actually perform object creation

The code at the beginning of ActivityCImpl.injectDoctorActivity() is extremely clear:

@Override
public void injectDoctorActivity(DoctorActivity doctorActivity) {
  injectDoctorActivity2(doctorActivity);}
  
  private DoctorActivity injectDoctorActivity2(DoctorActivity instance) {
  DoctorActivity_MembersInjector.injectMDoctor(instance, getDoctor());
  return instance;
}

private Doctor getDoctor() {
  return injectDoctor(Doctor_Factory.newInstance());}

It is to create objects step by step and assign values ​​to variables.

The sequence is to create a Doctor instance first, then create a Hospital instance, then assign a value to the Doctor's internal variable hospital, and then assign a value to the doctor variable of DoctorActivity.

So, when we call mDoctor in DoctorActivity's onCreate method, everything is created.

3. How objects in the Activity are added to life cycle management

Objects don't have a lifecycle of the Activity class! ! !

This is a complete misunderstanding! ! !

Added to the life cycle management is the component component!

Hilt will automatically create and destroy instances of the generated component classes according to the life cycle of the corresponding Android classes.

How Component components are added to life cycle management

First of all, start from the entrance

((DoctorActivity_GeneratedInjector) generatedComponent()).injectDoctorActivity(UnsafeCasts.<DoctorActivity>unsafeCast(this));

What exactly does this line of code do?

From the perspective of Hilt_DoctorActivity, it is reduced to:

new ActivityComponentManager(this).generatedComponent().injectDoctorActivity(this)

ActivityComponentManager: A manager used to manage the creation of components in an activity. From here, it should be noted that activity starts to be passed as a parameter, so it is guessed that the code after ActivityComponentManager will definitely process the life cycle of activity.

new ActivityComponentManager(this):

public ActivityComponentManager(Activity activity) {
  this.activity = activity;
  this.activityRetainedComponentManager =
      new ActivityRetainedComponentManager((ComponentActivity) activity);
}

The ActivityComponentManager object holds the activity, and a new activityRetainedComponentManager object is created as a parameter.

activityRetainedComponentManager variable:

private final GeneratedComponentManager<ActivityRetainedComponent> activityRetainedComponentManager;

It can be found that the actual type ActivityRetainedComponentManager is the same as ActivityComponentManager, and the parent class is GeneratedComponentManager, which means that this class is used to create a component. The difference is that the component type specified by ActivityRetainedComponentManager is ActivityRetainedComponent, and ActivityRetainedComponent indicates that the component has a life cycle.

Continue to follow up new ActivityRetainedComponentManager((ComponentActivity) activity):

ActivityRetainedComponentManager(ComponentActivity activity) {
  this.viewModelProvider =
      new ViewModelProvider(
          activity,
          new ViewModelProvider.Factory() {
            @NonNull
            @Override
            @SuppressWarnings("unchecked")
            public <T extends ViewModel> T create(@NonNull Class<T> aClass) {
              ActivityRetainedComponent component =
                  ((GeneratedComponentManager<LifecycleComponentBuilderEntryPoint>)
                          activity.getApplication())
                      .generatedComponent()
                      .retainedComponentBuilder()
                      .build();
              return (T) new ActivityRetainedComponentViewModel(component);
            }
          });
}

The work of ActivityRetainedComponentManager to create components is all provided by viewModelProvider. You can see that activity participates in the creation of viewModelProvider objects here.

ViewModelProvider: Provides the required viewModel for the scope

private final Factory mFactory;//负责创建一个 viewModel
private final ViewModelStore mViewModelStore; //用来存储 viewModel 的


public ViewModelProvider(@NonNull ViewModelStoreOwner owner, @NonNull Factory factory) {
    this(owner.getViewModelStore(), factory);
}
public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
    mFactory = factory;
    mViewModelStore = store;
}

From the construction method, Activity is also an implementation class of the ViewModelStoreOwner interface.

The creation of ViewModelProvider does not carry out too many logical operations. It just assigns values ​​to its two member variables. One is to get the viewModel storage in the activity, and the other is to create a viewModel factory class based on the activity.

All kinds of creation work is over, so in Hilt_DoctorActivity

protected void inject() {
  ((DoctorActivity_GeneratedInjector) generatedComponent()).injectDoctorActivity(UnsafeCasts.<DoctorActivity>unsafeCast(this));
}

The real implementer of generatedComponent() is a ViewModelProvider. ViewModelProvider will return an existing viewModel or create a new viewModel. The newly created viewModel will be added to the activity's viewmodelStore and associated with the activity. Therefore, the viewModel has a life cycle of the activity.

The addition of ViewModel is the key to giving components a life cycle

/**
*/
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
    ViewModel viewModel = mViewModelStore.get(key);//从容器里查找已存在的

    if (modelClass.isInstance(viewModel)) {
        if (mFactory instanceof OnRequeryFactory) {
            ((OnRequeryFactory) mFactory).onRequery(viewModel);
        }
        return (T) viewModel;
    } else {
        //noinspection StatementWithEmptyBody
        if (viewModel != null) {
            // TODO: log a warning.
        }
    }
    if (mFactory instanceof KeyedFactory) {
        viewModel = ((KeyedFactory) mFactory).create(key, modelClass);
    } else {
        viewModel = mFactory.create(modelClass);//创建新的
    }
    mViewModelStore.put(key, viewModel);
    return (T) viewModel;
}

viewModel = mFactory.create(modelClass) returns to the place where the factory parameter is created when creating viewModelProvider:

ActivityRetainedComponentManager(ComponentActivity activity) {
  this.viewModelProvider =
      new ViewModelProvider(
          activity,
          new ViewModelProvider.Factory() {
            @NonNull
            @Override
            @SuppressWarnings("unchecked")
            public <T extends ViewModel> T create(@NonNull Class<T> aClass) {
              ActivityRetainedComponent component =
                  ((GeneratedComponentManager<LifecycleComponentBuilderEntryPoint>)
                          activity.getApplication())
                      .generatedComponent()
                      .retainedComponentBuilder()
                      .build();
              return (T) new ActivityRetainedComponentViewModel(component);
            }
          });
}

Finally, an ActivityRetainedComponentViewModel object is created. As a viewmodel, it has a life cycle and it holds a component. And the component created here is the one needed in the Hilt_doctorActivity.inject() method.

The reason why the creation of the component and finally the object seems to be complicated, it feels like the proxy pattern is used everywhere.

Guess you like

Origin blog.csdn.net/xx23x/article/details/121636223