¿Cuál es el uso real de "HasFragmentInjector" en Dagger 2

He implementado dagger2 v2.2 anteriormente, pero ahora han añadido dagger.android parte también. Así que estoy creando el proyecto de la muestra con eso.

Soy consciente de la vieja metodología de @Provide y @Modules y @Components etc anotaciones, pero de Dagger 2.8 + que han añadido esta biblioteca de apoyo a Android también que tienen algunas nuevas inyecciones como @ActivityKey , @ContributesAndroidInjector , @ Subcomponent.Builder, etc

Así que mi pregunta es qué beneficios trae a la mesa.

¿Resuelve problemas como el método Inject con la clase base puede funcionar para todas las clases secundarias? O Cualquier otro beneficio?

Pregunta 2 – HasFragmentInjector es sólo para cargar el fragmento dentro de la actividad como lo hacíamos usando el gestor de fragmentos? O me falta algo?

Por favor, no downvote su pregunta más informativa para todos los usuarios de la biblioteca como la documentación de la biblioteca no proporcionan tales respuestas.

2 Solutions collect form web for “¿Cuál es el uso real de "HasFragmentInjector" en Dagger 2”

Primera pregunta

En Dagger 2.8+ han añadido esta biblioteca de soporte de android que también tienen algunas nuevas anotaciones como @ActivityKey , @ContributesAndroidInjector , @Subcomponent.Builder etc. Así que mi pregunta es qué beneficios trae a la mesa.

Esto ya se ha respondido en ¿Cuáles son las ventajas de usar DispatchingAndroidInjector y las otras clases dagger-android?

¿Resuelve problemas como no tener un método de inyección para una clase base que puede funcionar para todas las clases de niños?

Dagger 2 utiliza la generación de código en tiempo de compilación para la inyección de dependencia. En esto, es diferente de otros marcos de inyección de dependencia como Guice que inspeccionan sitios de inyección en tiempo de ejecución. Para que Dagger 2 funcione, en algún momento debe especificar el invariante del sitio de inyección. Por lo tanto nunca será posible escribir algo como:

 void inject(Activity activity); 

Dentro de un componente Daga 2 y que se inyecte todas las actividades.

Sin embargo, hay muchas mejoras con las nuevas clases disponibles en dagger-android. Mientras antes tendrías que escribir:

 void inject(MainActivity mainActivity); 

Y así sucesivamente para cada sitio de inyección diferente ahora puede escribir el siguiente código:

 @Module(subcomponents = MainActivitySubcomponent.class) public abstract class MainActivityModule { @Binds @IntoMap @ActivityKey(MainActivity.class) abstract AndroidInjector.Factory<? extends Activity> mainActivityInjectorFactory(MainActivitySubcomponent.Builder builder); } 

y entonces:

 AndroidInjection.inject(this); 

Dentro de su MainActivity en el punto apropiado.

Segunda pregunta

HasFragmentInjector es sólo para cargar Fragmento dentro de la actividad como hacíamos usando FragmentManager? O me falta algo?

HasFragmentInjector simplemente marca la clase donde el Fragmento debe obtener su AndroidInjector . Puedes verlo por ti mismo en el código de GitHub para AndroidInjection#inject(Fragment fragment) :

 public static void inject(Fragment fragment) { checkNotNull(fragment, "fragment"); HasFragmentInjector hasFragmentInjector = findHasFragmentInjector(fragment); Log.d(TAG, String.format( "An injector for %s was found in %s", fragment.getClass().getCanonicalName(), hasFragmentInjector.getClass().getCanonicalName())); AndroidInjector<Fragment> fragmentInjector = hasFragmentInjector.fragmentInjector(); checkNotNull(fragmentInjector,"%s.fragmentInjector() returned null", hasFragmentInjector.getClass().getCanonicalName()); fragmentInjector.inject(fragment); } 

Desde el javadoc, este método camina primero el fragmento padre, luego la Actividad, luego finalmente la Aplicación para encontrar HasFragmentInjector y usa el AndroidInjector<Fragment> para inyectar los campos del Fragmento.

Sin embargo, la presencia de HasFragmentInjector no significa que HasFragmentInjector comenzar a administrar Fragmentos usando Dagger 2:

 public class MainActivity { @Inject CoffeeFragment coffeeFragment; //no! don't do this @Inject TeaFragment teaFragment; //no! 

Debería seguir utilizando la forma idiomática de instanciar Fragmentos que está utilizando métodos estáticos de fábrica. Dagger 2 realizará la inyección para los campos dentro de los Fragmentos cuando se onAttach(Context context) su onAttach(Context context) cuando, por ejemplo, agrega el Fragmento utilizando una transacción o lo delega en un ViewPager. En lugar del ejemplo anterior, el siguiente código es una actividad muy simple con un ViewPager y dos fragmentos:

 public class MainActivity extends AppCompatActivity implements HasSupportFragmentInjector { @Inject DispatchingAndroidInjector<Fragment> fragmentDispatchingAndroidInjector; ViewPager mViewPager; @Override protected void onCreate(Bundle savedInstanceState) { AndroidInjection.inject(this); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); BeveragesPagerAdapter beveragesPagerAdapter = new BeveragesPagerAdapter(getSupportFragmentManager()); mViewPager = (ViewPager) findViewById(R.id.viewpager); mViewPager.setAdapter(beveragesPagerAdapter); } class BeveragesPagerAdapter extends FragmentStatePagerAdapter { public BeveragesPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int i) { switch (i) { case 0: return TeaFragment.instantiate(new Bundle()); case 1: return CoffeeFragment.instantiate(new Bundle()); default: throw new IllegalStateException(); } } @Override public int getCount() { return 2; } @Override public CharSequence getPageTitle(int position) { return "tab " + (position + 1); } } @Override public AndroidInjector<Fragment> supportFragmentInjector() { return fragmentDispatchingAndroidInjector; } } 

El FragmentStatePagerAdapter gestiona correctamente la gestión de los Fragmentos y no se inyectan como campos dentro de MainActivity.

Los Fragmentos se parecen a esto:

En CoffeeFragment.java :

 public class CoffeeFragment extends Fragment { public static CoffeeFragment instantiate(@Nullable Bundle arguments) { CoffeeFragment coffeeFragment = new CoffeeFragment(); coffeeFragment.setArguments(arguments); return coffeeFragment; } @Inject @Named("Coffee") Repository repository; TextView textView; @Override public void onAttach(Context context) { AndroidSupportInjection.inject(this); super.onAttach(context); } @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View v = inflater.inflate(R.layout.fragment_coffee, container, false); textView = (TextView) v.findViewById(R.id.coffee_textview); return v; } @Override public void onResume() { textView.setText(repository.retrieve()); } } 

En CoffeeFragmentModule.java :

 @Module(subcomponents = CoffeeFragmentSubcomponent.class ) public abstract class CoffeeFragmentModule { @Binds @Named("Coffee") abstract Repository repository(CoffeeRepository coffeeRepository); @Binds @IntoMap @FragmentKey(CoffeeFragment.class) abstract AndroidInjector.Factory<? extends Fragment> bindCoffeeFragmentInjectorFactory(CoffeeFragmentSubcomponent.Builder builder); } 

En CoffeeFragmentSubcomponent.java :

 @Subcomponent public interface CoffeeFragmentSubcomponent extends AndroidInjector<CoffeeFragment> { @Subcomponent.Builder abstract class Builder extends AndroidInjector.Builder<CoffeeFragment> {} } 

En CoffeeRepository.java :

 public class CoffeeRepository implements Repository { @Inject public CoffeeRepository() { } @Override public String retrieve() { return "Coffee!!!!"; } } 

La documentación oficial explica este tema bastante bien en mi opinión.

De todos modos el principal beneficio es que en lugar de algo como esto

 ((SomeApplicationBaseType) getContext().getApplicationContext()) .getApplicationComponent() .newActivityComponentBuilder() .activity(this) .build() .inject(this); 

Simplemente puede escribir esto, lo que hace la vida más fácil para todos.

 AndroidInjection.inject(this); 
  1. Menos ergonómica, facilidad de mantenimiento.

  2. El acercamiento anterior es clase de romper el concepto básico de la inyección de la dependencia, una clase no debe saber ningunos detalles sobre la manera que las dependencias se están inyectando.

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.