我在基础模块中有一个BaseUiFragment,需要注入一个UiComponent。
public abstract class BaseUiFragment extends Fragment {
@Inject
UiComponent mUiComponent;
@Override
public final void onAttach(Context context) {
AndroidSupportInjection.inject(this); //this is subclass
super.onAttach(context);
}
}
@Subcomponent
public interface BaseUiFragmentSubcomponent extends AndroidInjector<BaseUiFragment> {
@Subcomponent.Builder
abstract class Builder extends AndroidInjector.Builder<BaseUiFragment> {
}
}
@Module(subcomponents = BaseUiFragmentSubcomponent.class)
public abstract class BaseUiFragmentModule {
@Binds
@IntoMap
@FragmentKey(BaseUiFragment.class) // key in MapProviderFactory
abstract AndroidInjector.Factory<? extends Fragment>
bindBaseUiFragmentInjectorFactory(BaseUiFragmentSubcomponent.Builder builder);
private BaseUiFragmentModule() {}
}
在app模块中,UiComponentModule提供UiComponent,MainFragment扩展了BaseUiFragment。
@Module
public class UiComponentModule {
@Provides
static UiComponent provideUiComponent() {
return new UiComponent() {};
}
}
@Singleton
@Component(modules = {AndroidSupportInjectionModule.class, BaseUiFragmentModule.class, UiComponentModule.class})
public interface ApplicationComponent extends AndroidInjector<MainApplication> {
@Component.Builder
abstract class Builder extends AndroidInjector.Builder<MainApplication> {
}
}
public class MainFragment extends BaseUiFragment {
@Override
public View onCreateViewImpl(Bundle savedInstanceState) {
return new View(getContext());
}
}
当AndroidSupportInjection.inject(this);运行,它不起作用。 因为DispatchingAndroidInjector的maybeInject()返回false
injectorFactories有(BaseUiFragment.class,...)没有(MainFragment.class,...),但AndroidSupportInjection.inject(this);这是MainFragment。
public boolean maybeInject(T instance) {
Provider<AndroidInjector.Factory<? extends T>> factoryProvider =
injectorFactories.get(instance.getClass());
if (factoryProvider == null) { // factoryProvider is null
return false;
}
// ...
}
那么,如何在基类中使用AndroidInjection(AndroidSupportInjection)?
经过几天的分析:
Google注入impl:它只是 instance.getClass()
public boolean maybeInject(T instance) {
Provider<AndroidInjector.Factory<? extends T>> factoryProvider =
injectorFactories.get(instance.getClass());
if (factoryProvider == null) {
return false;
}
// ...
}
我的impl:遍历它和它的超类,问题解决了,但是它使用了获取factoryProvider的反射。
public boolean maybeInject(T instance) {
Provider<AndroidInjector.Factory<? extends Fragment>> factoryProvider
= injectorFactories.get(fragment.getClass());
Class fragmentSuperclass = fragment.getClass().getSuperclass();
while (factoryProvider == null && fragmentSuperclass != Fragment.class) {
factoryProvider = injectorFactories.get(fragmentSuperclass);
fragmentSuperclass = fragmentSuperclass.getSuperclass();
}
if (factoryProvider == null) {
return false;
}
// ...
}
那么,只是这样吗?谷歌可以改变实施吗?
答案 0 :(得分:2)
您只创建了一个知道如何注入BaseUiFragment
的子组件。由于这就是匕首所能看到的,它只会知道如何生成代码以处理注入BaseUiFragment
。
您需要为继承层次结构的每个叶子创建一个子组件。
这样的事情是我喜欢做片段组件的方式
@Subcomponent
public interface MainFragmentComponent extends AndroidInjector<MainFragment> {
@Subcomponent.Builder
abstract class Builder extends AndroidInjector.Builder<MainFragment> {}
@Module(subcomponents = MainFragmentComponent.class)
abstract class BindingModule {
@Binds
@IntoMap
@FragmentKey(MainFragment.class)
abstract Factory<? extends Fragment> mainFragmentComponentBuilder(Builder impl);
}
}