2017-05-21 5 views
0

ベースモジュールにBaseUiFragmentがあり、UiComponentを注入する必要があります。アプリケーションモジュールでAndroidInjectionをベースクラスで使用するには?

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() {} 
} 

、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(本)それは動作しません。 DispatchingAndroidInjectorのmaybeInject()がfalseを返すため、

injectorFactoriesには(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; 
    } 
    // ... 
} 

だから、それはこれだけの方法であるか、そしてGoogleは、実装を変更することができますか?

答えて

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); 
    } 
} 
+0

をしたいかである「あなたの継承階層の各リーフのためのサブコンポーネントを作成する」と思い、良い方法ではありません。私のベースライブラリを使用している呼び出し元には親切ではありません。 –

+0

@ApolunorJing Daggerは_コンパイル時コード生成ソリューションです。 'FooFragment'がフィールド' @Inject Bar bar'を持っていると、Daggerはコンパイル時にそれを検査せずに(つまり、そのためのセッターを書くことはできません)、そのようにする方法はまったくありませんTrevはここにそれを持っています。答えに+1。 –

関連する問題