在遵循良好的官方建议以注入和避免使用the authors themselves中繁琐的代码时,我在尝试使用支持库时遇到了麻烦。
根据文章:
AppCompat用户应继续实施
AndroidInjector.Factory<? extends Activity> and not <? extends AppCompatActivity>
(或FragmentActivity
)。
我坚持使用视图总是Fragment
的MVP架构,并且我不想让Activity
参与任何DI业务,但是我想知道这样做是否有必要但到目前为止,我还没有做到。如果我跳过全部支持内容,则该应用程序会在运行时崩溃,因为该片段的实例是受支持的(以防万一)。然后,我进入了尝试由于编译错误而尝试进行HasSupportFragmentInjector
而不是HasFragmentInjector
的大量更改的任务,由于我的心理健康,我的大脑已经忘记了这些错误。一段时间后,我开始思考非支持活动如何托管支持片段。啊!那些棘手的通配符。但是,无论我如何尝试遵循建议,如果没有EmptyModule
,我也无法想出一种方法,我也需要在Activity中对其进行设置,以便使用匕首和它(真的,对我而言仍然是魔术)。为什么我没有尝试过?我当然也可以,但是我对无望的改变感到厌倦,在这一点上我需要帮助。
AppModule.kt
@Singleton
@dagger.Module
class AppModule(val application: Application) {
@Provides @Singleton fun application(): Application = application
...
}
AppComponent.java
@ApplicationScope
@Singleton
@Component(modules = {
AndroidSupportInjectionModule.class,
...
FooFragmentModule.class,
})
public interface AppComponent {
Application app();
...
void inject(MyApp app);
}
MyApp.java
public class MyApp extends Application implements HasActivityInjector {
private AppComponent component;
public AppComponent someWayToReturnAppComponent() {
...
}
@Inject DispatchingAndroidInjector<Activity> dispatchingActivityInjector;
@Override
public void onCreate() {
component = DaggerAppComponent.builder()
.appModule(new AppModule(this))
// more app-scoped modules
.build();
component.inject(this);
}
@Override
public AndroidInjector<Activity> activityInjector() {
return dispatchingActivityInjector;
}
}
MainActivity.java
public abstract class MainActivity extends AppCompatActivity implements HasSupportFragmentInjector {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayout()); // inflate the fragment via XML here
}
@Inject DispatchingAndroidInjector<Fragment> dispatchingFragmentInjector;
@Override
public AndroidInjector<Fragment> fragmentInjector() {
return dispatchingFragmentInjector;
}
}
FooFragmentComponent.java
@Subcomponent
public interface FooFragmentComponent extends AndroidInjector<FooFragment> {
@Subcomponent.Builder
abstract class Builder extends AndroidInjector.Builder<FooFragment> {}
}
FooFragmentModule.kt
@dagger.Module(subcomponents = {FooFragmentComponent.class})
public abstract class FooFragmentModule {
@Binds
@IntoMap
@FragmentKey(FooFragment.class)
abstract AndroidInjector.Factory<? extends Fragment> bindFragmentInjectorFactory(FooFragmentComponent.Builder builder);
@ActivityScope
abstract FooFragment contributeFooFragmentInjector();
@Provides
static FooPresenter presenter() {
return new FooPresenter();
}
}
FooFragment
public class FooFragment extends Fragment implements SomeView {
@Inject FooPresenter presenter;
}
好。现在,回到
AppCompat用户应继续实施
AndroidInjector.Factory<? extends Activity>
我不需要(也愿意反对)仅将其用于片段。我是否真的需要为此设置模块和组件,或者我缺少什么?
编辑
在遵循EpicPandaForce使用AndroidSupportInjectionModule
的建议之后,Dagger现在抱怨
FragmentKey方法应该绑定
dagger.android.AndroidInjector.Factory<? extends android.app.Fragment>
,而不是dagger.android.AndroidInjector.Factory<? extends android.support.v4.app.Fragment>
。
答案 0 :(得分:2)
正如注释中提到的@EpicPandaForce一样,您需要使用AndroidSupportInjectionModule来支持片段。 您还需要使用the FragmentKey in dagger.android.support,而不是the one in dagger.android。这样可以使您在编辑过程中克服问题。
从广义上讲,support Fragments不要扩展base Fragments(无论如何,API 28及更高版本均已弃用)。这与AppCompatActivity及其超类the support library's FragmentActivity形成了鲜明的对比,后者都扩展了Android API级别1中引入的框架Activity。因此,无论您使用的是支持Fragments还是-在片段中,可能可能没有父AppCompatActivity,但总是具有某种Activity。这很重要,因为Android reserves the right to instantiate your Fragment using its necessary public no-arg constructor意味着Fragment只能使用在onAttach
中可以找到的东西(即其父片段,其Activity或其Application)进行自我注入。
dagger.android不关心您的Activity是否为AppCompatActivity,因为除了寻找自己的注射器之外,它不使用Activity。您可以在AndroidSupportInjection.findHasFragmentInjector私有方法中看到这一点,该方法(按顺序)检查父片段的层次结构,然后是Activity,然后是Application。因此,即使实际上说支持片段只能在支持活动上正常运行,dagger.android仍可以基于超类活动绑定其键,因为没有理由区分它们并设置两个单独的映射(Activity与AppCompatActivity)。即使有这样的分隔,您也可以将AppCompatActivity注入器绑定到您的Activity映射中,所有内容都将变得非常混乱。
如果没有活动范围的绑定,则还应从该搜索顺序中选择,不需要创建活动范围的组件;您可以让您的应用程序实现HasSupportFragmentInjector,将FooFragmentModule直接安装到AppComponent中,然后从MainActivity中删除HasSupportFragmentInjector。这是非典型的,因为大多数应用程序对Activity状态或应该注入的控制器有某种感觉(甚至只是注入Activity实例本身,其上下文或资源)。如果您只是想使用@ActivityScope
注释,那么您可以完全跳过该步骤,而只使用Application组件和几个Fragment子组件。但是,我认为您最终很有可能需要@ActivityScope
,因此尽早为其创建一个组件是很合理的。