作者:yangxin | 来源:互联网 | 2023-02-01 20:03
我之前已经实现了dagger2 v2.2但是现在他们也添加了dagger.android部分.所以我用它创建示例项目.
我知道有关的旧方法@Provide和@Modules和@Components等注解但是从匕首2.8+,他们也加入了这个Android的支持库,它有一些新的注射像@ActivityKey,@ContributesAndroidInjector,@ Subcomponent.Builder等.
所以我的问题是它带来了什么好处.
它是否解决了像基类的Inject方法可以适用于所有子类的问题?还是其他任何好处?
第二个问题 - HasFragmentInjector只是像我们以前使用片段管理器一样加载片段内部活动?或者我错过了一些东西?
请不要为所有图书馆用户提供更具信息性的问题,因为图书馆的文档没有提供这样的答案.
1> David Rawson..:
第一个问题
在匕首2.8+他们将此Android的支持库还具有一些新的注解像@ActivityKey
,@ContributesAndroidInjector
,@Subcomponent.Builder
等等.所以我的问题是什么好处,它带来的表.
这已经回答了使用DispatchingAndroidInjector和其他dagger-android类有什么好处?
它是否解决了没有一个可以适用于所有子类的基类的注入方法的问题?
Dagger 2在编译时使用代码生成来进行依赖注入.在这方面,它与Guice等其他依赖注入框架不同,它们在运行时检查注入站点.为了使Dagger 2工作,您必须在某一时刻指定注射部位的不变量.因此永远不可能写出如下内容:
void inject(Activity activity);
在Dagger 2组件中,让它注入所有活动.
但是,dagger-android中提供的新类有很多改进.在你必须写之前:
void inject(MainActivity mainActivity);
对于每个不同的注射部位,您现在可以编写以下代码:
@Module(subcompOnents= MainActivitySubcomponent.class)
public abstract class MainActivityModule {
@Binds
@IntoMap
@ActivityKey(MainActivity.class)
abstract AndroidInjector.Factory extends Activity> mainActivityInjectorFactory(MainActivitySubcomponent.Builder builder);
}
然后:
AndroidInjection.inject(this);
在适当的时间点在MainActivity中.
第二个问题
HasFragmentInjector只是像我们以前使用FragmentManager那样在Activity里面加载Fragment?或者我错过了什么?
HasFragmentInjector
只是标记Fragment应该从中获取它的类AndroidInjector
.您可以在代码中看到自己在GitHub上进行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 fragmentInjector = hasFragmentInjector.fragmentInjector();
checkNotNull(fragmentInjector,"%s.fragmentInjector() returned null",
hasFragmentInjector.getClass().getCanonicalName());
fragmentInjector.inject(fragment);
}
从javadoc开始,此方法首先遍历父片段,然后是Activity,最后是Application,以查找HasFragmentInjector
并使用它AndroidInjector
来注入片段的字段.
但是,存在HasFragmentInjector
并不意味着您应该使用Dagger 2开始管理Fragments:
public class MainActivity {
@Inject CoffeeFragment coffeeFragment; //no! don't do this
@Inject TeaFragment teaFragment; //no!
您仍应使用实例化使用静态工厂方法的Fragments的惯用方法.当onAttach(Context context)
调用它们时,Dagger 2将对Fragments中的字段执行注入,例如,您使用事务添加Fragment或委托给ViewPager.以下代码是一个非常简单的Activity,带有ViewPager和两个片段,而不是上面的例子:
public class MainActivity extends AppCompatActivity implements HasSupportFragmentInjector {
@Inject
DispatchingAndroidInjector 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 supportFragmentInjector() {
return fragmentDispatchingAndroidInjector;
}
}
FragmentStatePagerAdapter正确处理Fragments的管理,我们不会在MainActivity中注入字段.
片段本身看起来像这样:
在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());
}
}
在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);
}
在CoffeeFragmentSubcomponent.java中:
@Subcomponent
public interface CoffeeFragmentSubcomponent extends AndroidInjector {
@Subcomponent.Builder
abstract class Builder extends AndroidInjector.Builder {}
}
在CoffeeRepository.java中:
public class CoffeeRepository implements Repository {
@Inject
public CoffeeRepository() {
}
@Override
public String retrieve() {
return "Coffee!!!!";
}
}