gpt4 book ai didi

android - Dagger2 注入(inject)大量的activity/fragments/services(可能得到大量的NPE)

转载 作者:搜寻专家 更新时间:2023-11-01 08:31:36 25 4
gpt4 key购买 nike

我们使用了 RoboGuice,但它已被弃用,我开始用 Dagger2 替换它。

// https://github.com/google/dagger
compile('com.google.dagger:dagger:2.7')
annotationProcessor 'com.google.dagger:dagger-compiler:2.7'
provided 'org.glassfish:javax.annotation:10.0-b28'

@Module
public class ApplicationModule {
Application mApp;

public ApplicationModule(@NonNull Application app) {
Preconditions.checkNotNull(app);
mApp = app;
}

@Provides
@Singleton
public SharedPreferences providesSharedPrefs() {
return PreferenceManager.getDefaultSharedPreferences(mApp);
}

@Provides
@Singleton
public DateHelper providesDateHelper() {
return new DateHelper(mApp);
}

@Provides
@Singleton
public PersistentConfig providesPersistentConfig() {
return new PersistentConfig(mApp);
}

@Provides
@Singleton
public OttoBus providesOttoBus() {
return new OttoBus();
}
}

public class Application extends MultiDexApplication {
private ApplicationComponent mApplicationComponent;

@Override
public void onCreate() {
super.onCreate();
mApplicationComponent = DaggerApplicationComponent.builder()
.applicationModule(new ApplicationModule(this))
.build();
mApplicationComponent.inject(this);
}

public static Application getApp(@NonNull Context context) {
return (Application) context.getApplicationContext();
}

public static ApplicationComponent getApplicationComponent(@NonNull Context context) {
return getApp(context).getApplicationComponent();
}
}

在我想注入(inject) ApplicationComponent 的所有地方之后

例如MainActivity

public class MainActivity extends AppCompatActivity {
@Inject
PersistentConfig mPersistentConfig;

@Inject
OttoBus mOttoBus;

@Override
public void onCreate(Bundle savedInstanceState) {
Helper.manageRotation(this);
super.onCreate(null);
setContentView(R.layout.main_layout);
Application.getApplicationComponent(this).inject(this);
}
}

Application.getApplicationComponent(context).inject(this);

第一个问题:我对interface ApplicationComponent感到很困惑。它必须在我想使用注入(inject)的地方提供所有 Activity/fragment/服务(等)。但我不能使用像 Activity / Fragment 这样的通用对象.还是我真的脱离了现实,不了解 Dagger2 的工作原理?

因为这对于具有大约 50 多个 Activity 和大量 fragment/服务的项目来说真的很疯狂......

@Singleton
@Component(modules = {ApplicationModule.class})
public interface ApplicationComponent {
void inject(@NonNull Application app);
void inject(@NonNull MainActivity object);
void inject(@NonNull DispatcherActivity object);
void inject(@NonNull DateTimeHelper object);
void inject(@NonNull DatabaseHelper object);
void inject(@NonNull LandingPageActivityFragment object);
void inject(@NonNull RedirectActivity object);
void inject(@NonNull CategoryFragment object);
void inject(@NonNull BaseModuleFragment object);
void inject(@NonNull NotificationHelper object);
void inject(@NonNull RecordAdapter object);
void inject(@NonNull PagingProvider object);
void inject(@NonNull FilterDialog object);
... next 100+ injections?
}

我说,这不可能是真的......

第二个问题:当我不能像void inject(@NonNull NotificationHelper<? extends GenericObject> object);那样使用它时,我如何提供注入(inject)泛型类?因为它需要特定的对象。所以我必须把所有这些对象写在ApplicationComponent里面并且不使用 ?符号?

这不仅仅是疯狂 :(。也许最好继续使用 RoboGuice,它对开发人员更加友好,并且不需要产生这种开销并手动检查每个注入(inject)的对象?当我忘记将它们添加到此列表时,我会在运行时获取 NPE(当我不对其进行大量测试时,它会使客户崩溃)。

当不可能使用像Activity / Fragment / Service 这样的通用对象时,手动编写它比列出所有对象要快得多。 .

有没有更好的解决方案,当我不想使用相同的通用 BaseActivity这将注入(inject) ApplicationModule 的每一部分每个 Activity 都将由这个巨大的 BaseActivity 扩展?

最佳答案

这个问题有投诉的方面,但要尝试回答:

I'm really confused about interface ApplicationComponent which must provide all activities/fragments/services (etc) where I want to use injection. But I can't use generic objects like Activity / Fragment. Or am I really out of reality and don't understand how Dagger2 works?

确实,这就是 Dagger 2 的工作原理;它必须在注入(inject)器(组件)内静态提供注入(inject)目标的类型,并且不能使用“通用”(协变)类型。 Dagger 2 这样做是为了维护一个 100% 静态的 DI 框架。

请注意,您指定的是 RecordAdapterDatabaseHelper作为注入(inject)部位。您可能不需要这样做,您应该尝试仅指定构造函数不可见的顶级对象( ActivityFragmentService )作为注入(inject)站点。其余对象应该能够通过使用 @Inject 注释它们的依赖关系来构建。并在 Module 中指定它们的依赖关系(如果有的话) .

Maybe better stay with RoboGuice which is much more developer friendly and don't need make this overhead and manual check every injected objects

是的,Roboguice 更友好,因为您不必担心指定注入(inject)目标。但是,请考虑 Roboguice 中的以下内容: 1. 错误设置对象图时出现的“死亡的红色堆栈跟踪”2. 事实上,您无法通过 Find Usages 查看您的项目中实际使用了哪些接口(interface)实现,这也可能是“开发人员不友好”

Is there a better solution, when I don't want use same generic BaseActivity which will inject every part of ApplicationModule and every activity will be extended by this huge BaseActivity?

好吧,这取决于您使用的依赖项以及使用的位置。如果你有一小部分依赖项要到处注入(inject),那可能是最好的解决方案,即制作一个BaseActivity。接收这些注入(inject)并使它可用于您的所有子类。或者,您可以使用子组件和模块来划分您的对象图,以便您可以将消费者/注入(inject)目标与正确的模块组合在一起。这样一来,您就不需要一个列出所有注入(inject)部位的“上帝”组件。

Second question: How I can provide to inject generic classes, when I can't use it like void inject(@NonNull NotificationHelper object); because it require specific object. So I must write all this objects inside ApplicationComponent and not use ? notation?

是的,您必须提供注入(inject)目标的不变类型。我不确定你的 NotificationHelper<String>是顶级类型。当你注入(inject) Fragment 时,为什么不通过对象图注入(inject)它呢? , ActivityService

如果它绝对必须是一个注入(inject)目标,您将需要子类化:NotificationHelper<String>Notification<Integer>成为StringNotificationHelper extends NotificationHelper<String> , IntegerNotficationHelper extends NotificationHelper<Integer> .这是《清洁代码》一书中推荐的做法。

您不需要将所有注入(inject)点都写在 ApplicationComponent 中,您可以创建与项目中依赖项的消费模式相对应的子组件。

(披露:作为目前正在尝试将项目从 Roboguice 迁移到 Dagger 2 的人,我对您的投诉表示同情)

关于android - Dagger2 注入(inject)大量的activity/fragments/services(可能得到大量的NPE),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40206831/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com