¿Qué determina el ciclo de vida de un componente (gráfico de objeto) en Dagger 2?

Estoy tratando de comprender los ámbitos en Dagger 2, específicamente el ciclo de vida de los gráficos de ámbito. ¿Cómo se crea un componente que se limpiará cuando abandone el ámbito?

En el caso de una aplicación de Android, al usar Dagger 1.x generalmente tiene un alcance raíz en el nivel de la aplicación que extendería para crear un alcance secundario en el nivel de actividad.

public class MyActivity {

    private ObjectGraph mGraph;

    public void onCreate() {
        mGraph = ((MyApp) getApplicationContext())
            .getObjectGraph()
            .plus(new ActivityModule())
            .inject(this);
    }

    public void onDestroy() {
        mGraph = null;
    }
}

El ámbito secundario existió siempre que mantuviera una referencia a él, que en este caso fue el ciclo de vida de su Actividad. Dejar caer la referencia en onDestroy aseguró que el gráfico de alcance fuera libre para ser recolectado.

EDITAR

Jesse Wilson recientemente publicó unmea culpa

Dagger 1.0 jodió mal sus nombres de alcance ... La anotación @Singleton se usa tanto para gráficos raíz como para gráficos personalizados, por lo que es difícil descubrir cuál es el alcance real de una cosa.

y todo lo demás que he leído / escuchado apunta a Dagger 2 mejorando la forma en que funcionan los ámbitos, pero me cuesta entender la diferencia. Según el comentario de @Kirill Boyarshinov a continuación, el ciclo de vida de un componente o dependencia aún está determinado, como de costumbre, por referencias concretas. Entonces, ¿la diferencia entre los alcances Dagger 1.xy 2.0 es puramente una cuestión de claridad semántica?

Mi punto de vistaDaga 1.x

Las dependencias eran@Singleton o no. Esto fue igualmente cierto para las dependencias en el gráfico raíz y los subgrafos, lo que lleva a la ambigüedad en cuanto a qué gráfico estaba vinculada la dependencia (verEn Dagger, ¿están los Singleton dentro del sub-gráfico en caché o siempre se recrearán cuando se construya un nuevo sub-gráfico de actividad?)

Daga 2.0

Los ámbitos personalizados le permiten crear ámbitos semánticamente claros, pero son funcionalmente equivalentes a la aplicación@Singleton en Dagger 1.x.

// Application level
@Singleton
@Component( modules = MyAppModule.class )
public interface MyAppComponent {
    void inject(Application app);
}

@Module
public class MyAppModule {

    @Singleton @Named("SingletonScope") @Provides
    StringBuilder provideStringBuilderSingletonScope() {
        return new StringBuilder("App");
    }
}
// Our custom scope
@Scope public @interface PerActivity {}
// Activity level
@PerActivty
@Component(
    dependencies = MyAppComponent.class,
    modules = MyActivityModule.class
)
public interface MyActivityComponent {
    void inject(Activity activity);
}

@Module
public class MyActivityModule {

    @PerActivity @Named("ActivityScope") @Provides
    StringBuilder provideStringBuilderActivityScope() {
        return new StringBuilder("Activity");
    }

    @Name("Unscoped") @Provides
    StringBuilder provideStringBuilderUnscoped() {
        return new StringBuilder("Unscoped");
    }
}
// Finally, a sample Activity which gets injected
public class MyActivity {

    private MyActivityComponent component;

    @Inject @Named("AppScope")
    StringBuilder appScope

    @Inject @Named("ActivityScope")
    StringBuilder activityScope1

    @Inject @Named("ActivityScope")
    StringBuilder activityScope2

    @Inject @Named("Unscoped")
    StringBuilder unscoped1

    @Inject @Named("Unscoped")
    StringBuilder unscoped2

    public void onCreate() {
        component = Dagger_MyActivityComponent.builder()
            .myApplicationComponent(App.getComponent())
            .build()
            .inject(this);

        appScope.append(" > Activity")
        appScope.build() // output matches "App (> Activity)+" 

        activityScope1.append("123")
        activityScope1.build() // output: "Activity123"

        activityScope2.append("456")
        activityScope1.build() // output: "Activity123456"

        unscoped1.append("123")
        unscoped1.build() // output: "Unscoped123"

        unscoped2.append("456")
        unscoped2.build() // output: "Unscoped456"

    }

    public void onDestroy() {
        component = null;
    }

}

La conclusión es que usando@PerActivity comunica tuintención con respecto al ciclo de vida de este componente, pero finalmente puede usar el componente en cualquier lugar / en cualquier momento. La única promesa de Dagger es que, para un componente dado, los métodos anotados en el alcance devolverán una sola instancia. También supongo que Dagger 2 usa la anotación de alcance en el componente para verificar que los módulos solo proporcionen dependencias que estén en el mismo alcance o sin alcance.

En resumen

Las dependencias siguen siendo singleton o no singleton, pero@Singleton ahora está destinado a instancias de singleton a nivel de aplicación y los ámbitos personalizados son el método preferido para anotar dependencias de singleton con un ciclo de vida más corto.

El desarrollador es responsable de administrar el ciclo de vida de los componentes / dependencias eliminando referencias que ya no son necesarias y responsable de garantizar que los componentes solo se creen una vez en el alcance para el que están destinados, pero las anotaciones de alcance personalizadas hacen que sea más fácil identificar ese alcance .

La pregunta de $ 64k *

¿Es correcto mi comprensión de los ámbitos y ciclos de vida de Dagger 2?

* No es realmente una pregunta de $ 64,000.

Respuestas a la pregunta(1)

Su respuesta a la pregunta