java - medium - dagger android processor
Daga 2 alcance y subcomponentes (1)
Un poco radical, pero para simplificar las cosas: todas las anotaciones de alcance no son más que azúcar sintáctica, incluido @Singleton
.
Los alcances en su mayoría solo proporcionan controles de tiempo de compilación. Dependencias cíclicas, o errores sobre cosas que podrías haber pasado por alto. @Singleton
es como cualquier otro ámbito, la única diferencia es que es una anotación ya existente y no tiene que crearla usted mismo. Puedes usar @MySingleton
en @MySingleton
lugar.
[...] daga está creando un objeto en algún grupo estático que existirá durante todo el ciclo de vida de la aplicación
No. Daga no hace nada estático. Tienes objetos componentes. Esos componentes contienen tus objetos creados por módulos. Si un objeto en un componente tiene el alcance del componente, solo se creará una vez en ese componente exacto . Si decide crear 2 objetos AppComponent
, tendrá 2 objetos de cada objeto anotado @Singleton
, cada uno dentro de su componente. Por eso debes mantener la referencia al componente. La mayoría de las implementaciones que he visto o usado mantienen su AppComponent
dentro de su Application
. Si haces esto, puedes usarlo como un singleton, todavía es solo un POJO.
[...] coloca el componente @PerFragment en la clase de Aplicación que vivirá mientras dure la Aplicación.
Sí. Como ya se ha cubierto en el párrafo anterior, es solo un objeto. Guarda la referencia, tú guardas los objetos. Deséchelo o cree uno nuevo y tiene nuevos objetos (definidos en este componente / ámbito). No obstante, debe mantener los componentes de la actividad o del ámbito de los fragmentos en cualquier lugar, además de en los de las actividades o los fragmentos, ya que mantenerlos, por ejemplo, en el componente de su aplicación, probablemente generará una pérdida de memoria. (Si no es así, probablemente no habría necesitado la actividad o el alcance del fragmento).
si dagger encuentra la anotación
@Singleton
, agregará una referencia estática al componente cuando se cree por primera vez y, en caso de cualquier otra anotación, no mantendrá la referencia al componente.
De nuevo, no. Nada estático. Objetos de Java antiguos simples. Puede tener múltiples componentes @Singleton
con sus propios objetos, pero probablemente no debería (aunque esto es lo que hace posible / fácil la prueba de instrumentación, simplemente intercambiar componentes).
Tu error mencionado
SpiceManager no se puede proporcionar sin un constructor @Inject o desde un método anotado @ Provides- o @ Produces.
Esto significa que el componente con el que está intentando inyectar su objeto no puede encontrar ninguna forma de producir o proporcionar un SpiceManager
. Asegúrese de proporcionarlo desde su AppComponent o en algún otro lugar, no le faltan anotaciones, etc.
Estoy tratando de hacer que mi aplicación sea mejor y el código sea más Dagger2
mantener usando Dagger2
Tomé una idea general, pero aún no puedo entender cómo se gestionan los ámbitos con Dagger2
. Dagger2
daga en mi proyecto (suena gracioso). ApplicationComonent
componente ApplicationComonent
y funciona perfectamente en mi proyecto. Aquí está mi código.
@Singleton
@Component(modules = {
ApplicationModule.class,
ThreadingModule.class,
NetworkModule.class,
DatabaseModule.class,
ServiceModule.class,
ParseModule.class,
PreferencesSessionModule.class})
public interface ApplicationComponent {
ActivityComponent activityComponent(ActivityModule activityModule);
void inject(BaseActivity baseActivity);
void inject(MainAppActivity mainAppActivity);
void inject(MyApplication application);
void inject(BaseFragment baseFragment);
void inject(MyService service);
void inject(RegistrationIntentService service);
}
Creo mi instancia de componente en la clase MyApplication
como esta
private void initializeAndInjectComponent() {
mApplicationComponent =
DaggerApplicationComponent
.builder()
.threadingModule(new ThreadingModule(1))
.applicationModule(new ApplicationModule(this))
.networkModule(new NetworkModule(
MyService.API_SERVER_BASE_URL,
MyService.TIMEOUT))
.build();
mApplicationComponent.inject(this);
}
Y puedo obtener el componente para inyectar en mis Activities
MyApplication application = MyApplication.get(this);
application.getApplicationComponent().inject(this);
Todo funciona perfectamente.
Para agregar cada método y la clase de módulo se anota con el alcance @Singleton
, todos los módulos relacionados con ApplicationComponent
Ahora quiero mejorar las dependencias y he visto muchos ejemplos con ámbitos personalizados como @PerActivity
, @PerFragment
. Tengo muchas preguntas, pero sobre esto más tarde.
Así que creé ActivityComponent
@PerActivity
@Subcomponent(
modules = {
NetworkServiceModule.class,
ActivityModule.class,
PermissionModule.class
})
public interface ActivityComponent {
Activity activity();
void inject(BaseActivity baseActivity);
}
Todos los módulos se ven así
@PerActivity
@Module
public class ActivityModule {
private Activity mActivity;
public ActivityModule(Activity activity) {
this.mActivity = activity;
}
@Provides
@PerActivity
Activity provideActivity() {
return this.mActivity;
}
}
Tengo dependencias siguientes en mi BaseActivity
// Dependencies from ApplicationComponent
@Inject
protected ApplicationSettingsManager mApplicationSettingsManager;
@Inject
protected ScheduledThreadPoolExecutor mPoolExecutor;
// Dependencies from ActivityComponent
@Inject
protected SpiceManager mSpiceManager;
@Inject
protected PermissionController mPermissionController;
Y en mi método onCreate()
estoy inyectando como sigue
MyApplication application = MyApplication.get(this);
application.getApplicationComponent().activityComponent(new ActivityModule(this)).inject(this);
Antes de crear el subcomponente ActivityComponent
era
MyApplication application = MyApplication.get(this);
application.getApplicationComponent().inject(this);
Ahora tengo un error
Error:(34, 10) error: com.octo.android.robospice.SpiceManager cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method.
BaseActivity.mSpiceManager
[injected field of type: com.octo.android.robospice.SpiceManager mSpiceManager]
No puedo averiguar dónde está el problema, lo que me perdí. Mis preguntas sobre los alcances en daga2.
Todo menos @Singleton
es ignorado por Dagger 2, ¿verdad? ¿No entiendo cómo se maneja la vida del componente? Solo tengo una idea
Cuando se usa
@Singleton
anotación daga crea un objeto en algún grupo estático que existirá durante todo el ciclo de vida de la aplicación y se destruirá cuando se destruya la instancia del proceso JVM (dalvik VM, ART).Cuando usas cualquier otra anotación es solo para ti como desarrollador para mantener mejor el código,
@PerActivity
,@PerFragment
es solo una anotación personalizada, nada más. Y en caso de que coloque el componente@PerFragment
en la clase de Aplicación, vivirá mientras la Aplicación esté@PerFragment
. Estoy en lo ciertoEntonces entiendo esto de esta manera, si dagger encuentra la anotación
@Singleton
, agregará una referencia estática al componente cuando se cree por primera vez y, en caso de cualquier otra anotación, no mantendrá la referencia al componente.
Le agradecería cualquier ayuda con los problemas descritos anteriormente.
ACTUALIZAR
Gracias, David Medenjak
por una gran respuesta. Comprendí mucho mejor a Dagger2
.
También acabo de encontrar el problema, en la medida en que estoy usando un componente de Activity
separado ahora, olvidé dos líneas en ApplicationComponent
y cambio la función en mi MainActivity
a ActivityComponent
lugar de ApplicationComponent
, así que seguro que no pudo resolver las dependencias del subcomponente.
void inject(BaseActivity baseActivity);
void inject(MainAppActivity mainAppActivity);
Ahora todo funciona perfectamente, me gusta Dagger2
y la arquitectura separada.