Dagger Hilt-Dependency Injection and Implementation Principle of ViewModel

Inserte la descripción de la imagen aquí

Empuñadura de daga

Hilt es la última biblioteca DI lanzada por Google, que reduce el costo de usar Dagger en Android y admite la inyección de varios componentes comunes de Android, incluido nuestro ViewModel de uso común.

El artículo Dagger Hilt-Dependency Injection Framework recomendado oficialmente por Android presenta el método de inyección de ViewModel, que es muy simple de usar:

class ActivityViewModel @ViewModelInject constructor(
    private val repository: Repository,
    @Assisted private val savedState: SavedStateHandle
) : ViewModel() {
    
    

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

    private val viewModel by viewModels<ActivityViewModel>()

    override fun onCreate(savedInstanceState: Bundle?) {
    
    
        super.onCreate(savedInstanceState)

    }
}

La creación de ViewModle debe ViewModel.Factorycrearse directamente con la ayuda de en lugar del constructor. Todo el proceso de inyección anterior no personaliza ninguna fábrica, solo @ViewModelInjectse hace una anotación, ¿cómo se logra esto?

viewModels {…}

viewModels{...}Es una Lazy<>extensión ktx heredada que puede bycrear fácilmente un ViewModel a través de palabras clave. He Mvrxvisto un uso similar en airbnb antes, y parece que fue prestada por Jetpack.

El funcionario no solo está tomando prestado (chao) Jian (xi), tiene sus propios secretos

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

    return ViewModelLazy(VM::class, {
    
     viewModelStore }, factoryPromise)
}

Sabiendo por el código fuente, ViewModel.Factory se usa por defecto defaultViewModelProviderFactory. Entonces, siempre que reescriba este defaultViewModelProviderFactory, puede conectar la implementación personalizada en él

Anular getDefaultViewModelProviderFactory

Por el artículo anterior, sabemos que Hilt modificará la clase padre del objeto inyectado en tiempo de compilación.

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

MainActivity originalmente heredado de AppCompatActivity, pero después del procesamiento de Hilt, la clase padre se convierte enHilt_MainActivity

@Generated("dagger.hilt.android.processor.internal.androidentrypoint.ActivityGenerator")
public abstract class Hilt_MainActivity extends AppCompatActivity implements GeneratedComponentManager<Object> {
    
    
  private volatile ActivityComponentManager componentManager;
...
  @Override
  public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
    
    
    ViewModelProvider.Factory factory = DefaultViewModelFactories.getActivityFactory(this);
    if (factory != null) {
    
    
      return factory;
    }
    return super.getDefaultViewModelProviderFactory();
  }
}

HIlt_MainActivity DefaultViewModelFactories.getActivityFactory(this)devuelve ViewModel.Factory hasta .

public final class DefaultViewModelFactories {
    
    

  @Nullable
  public static ViewModelProvider.Factory getActivityFactory(ComponentActivity activity) {
    
    
    return getFactoryFromSet(
        EntryPoints.get(activity, ActivityEntryPoint.class).getActivityViewModelFactory());
  }
  //...
}

Resumen de una oración: Hilt obtiene ViewModelFactory a través de Component generado por Dagger

  • EntryPoints.get(activity, ActivityEntryPoint.class)Crear y obtener ActivityComponent,
  • getActivityViewModelFactory()Obtener fábrica a través del módulo en componente

Crear componente de actividad

public final class EntryPoints {
    
    

  @Nonnull
  public static <T> T get(Object component, Class<T> entryPoint) {
    
    
    if (component instanceof GeneratedComponent) {
    
    
      return entryPoint.cast(component);
    } else if (component instanceof GeneratedComponentManager) {
    
    
      return entryPoint.cast(((GeneratedComponentManager<?>) component).generatedComponent());
    } 
  }
}
@Generated("dagger.hilt.android.processor.internal.androidentrypoint.ActivityGenerator")
public abstract class Hilt_MainActivity extends AppCompatActivity implements GeneratedComponentManager<Object> {
    
    
  private volatile ActivityComponentManager componentManager;
...

  @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;
  }

Como arriba, Hilt_MainActivity hereda GeneratedComponentManager, ActivityComponentManager se generaComponent

public class ActivityComponentManager implements GeneratedComponentManager<Object> {
    
    

 //...

  protected Object createComponent() {
    
    
    return ((ActivityComponentBuilderEntryPoint)
            activityRetainedComponentManager.generatedComponent())
        .activityComponentBuilder()
        .activity(activity)
        .build();
  }
}

Finalmente ActivityComponentManager, ActivityComponent se crea mediante la adquisición de Hilt_MainActivity , y activityRetainedComponentManager (con la ayuda de ViewModel) en ActivityComponentManager asegura la reutilización del ActivityComponent.

Obtener ViewModelFactory

Después de obtener ActivityComponent, obtenga ViewModelFactory a través del modelo interno.
Se proporciona empuñadura ActivityModule, puede InstallInhacerlo ActivityComponent. El proveedor de fábrica se define en ActivityModule

@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
public final class ViewModelFactoryModules {
    
    

    /**
     * Hilt Modules for providing the activity level ViewModelFactory
     */
    @Module
    @InstallIn(ActivityComponent.class)
    public abstract static class ActivityModule {
    
    

        @NonNull
        @Multibinds
        abstract Map<String, ViewModelAssistedFactory<? extends ViewModel>> viewModelFactoriesMap();

        @Provides
        @IntoSet
        @NonNull
        @DefaultActivityViewModelFactory
        static ViewModelProvider.Factory provideFactory(
                @NonNull Activity activity,
                @NonNull Application application,
                @NonNull Map<String, Provider<ViewModelAssistedFactory<? extends ViewModel>>>
                        viewModelFactories) {
    
    
            // Hilt guarantees concrete activity is a subclass of ComponentActivity.
            SavedStateRegistryOwner owner = (ComponentActivity) activity;
            Bundle defaultArgs = activity.getIntent() != null
                    ? activity.getIntent().getExtras() : null;
            SavedStateViewModelFactory delegate =
                    new SavedStateViewModelFactory(application, owner, defaultArgs);
            return new HiltViewModelFactory(owner, defaultArgs, delegate, viewModelFactories)

Por SavedStateViewModelFactoryel defaultArgs, se implantan los parámetros deseados ViewModel

para resumir

Hilt reescribe la clase principal de Activity o Fragment en tiempo de compilación y obtiene el método personalizado ViewModel.Factory, enganchando así el proceso de creación de ViewModle e inyectando ViewModel. El proceso de implementación se basa en su conjunto @InstallIny @AndroidEntryPointlas anotaciones, que en sí mismo es una buena práctica empuñadura, vale la pena el aprendizaje y el aprendizaje a partir de


Consulte el artículo anterior
Dagger Hilt-Android marco de inyección de dependencia recomendado oficialmente

Supongo que te gusta

Origin blog.csdn.net/vitaviva/article/details/107124289
Recomendado
Clasificación