gpt4 book ai didi

Android Dagger 2.14 设置

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:56:16 24 4
gpt4 key购买 nike

我正在尝试弄清楚如何使用 dagger 2 设置 android 项目,但我做错了。 Dagger 2 和 android 依赖注入(inject)对我来说是相对较新的概念。

这是我的设置。

// App.java root of the application
public class App extends DaggerApplication {
@Override
protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
AppComponent appComponent = DaggerAppComponent.create();
appComponent.inject(this);
return appComponent;
}
}

// AppComponent.java component
@Component(modules = {
AndroidSupportInjectionModule.class,
AppBuilder.class,
SplashModule.class,
AppModule.class})
public interface AppComponent extends AndroidInjector<App> {
}

// AppBuilder.java module which bootstraps activities
@Module
public abstract class AppBuilder {
@ContributesAndroidInjector
abstract SplashActivity splashActivityInjector();
}

我还有扩展 DaggerAppCompatActivity 和 SplashModule 的 Activity ,后者处理 SplashActivity 中的依赖注入(inject)

现在这个设置开始工作了,我可以像这样在我的 SplashActivity 中注入(inject) MVP 模式展示器:

// inside SplashActivity
@Inject
SplashContract.Presenter mPresenter;

演示者中的 MVP View

// SplashPresenter
@Inject
SplashContract.View view;

到目前为止一切顺利。但是现在我想在我的演示者中进行额外的注入(inject):

@Inject
AppDataManager appDataManager;

AppDataManager 类需要构建应用程序上下文。而且每个应用程序我只需要 1 个 AppDataManager 实例。我不知道该怎么做,有很多例子,但他们使用不同的Dagger 2 版本,因为我对它没有真正的经验,所以会感到困惑。

我尝试设置额外的 AppModule 类来处理 AppDataManager 的配置,但它在运行时崩溃了。

// AppModule.java
@Module
public class AppModule {
private Context mContext;

public AppModule(Context context) {
mContext = context;
}

@Provides
@Singleton
Context provideContext() {
return mContext;
}

@Provides
@Singleton
AppDataManager provideAppDataManager(Context context) {
return new AppDataManager(context);
}
}

我做错了什么? (我怀疑我应该以不同的方式定义 AppModule)。

编辑 Logcat:

FATAL EXCEPTION: main
Process: com.domain.application, PID: 16075
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.domain.application/com.domain.application.ui.splash.SplashActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean com.domain.application.data.AppDataManager.isUserLoggedIn()' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2984)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3045)
at android.app.ActivityThread.-wrap14(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1642)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6776)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean com.domain.application.data.AppDataManager.isUserLoggedIn()' on a null object reference
at com.domain.application.ui.splash.SplashPresenter.openNextActivity(SplashPresenter.java:25)
at com.domain.application.ui.splash.SplashActivity.onCreate(SplashActivity.java:20)
at android.app.Activity.performCreate(Activity.java:6955)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1126)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2927)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3045) 
at android.app.ActivityThread.-wrap14(ActivityThread.java) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1642) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:154) 
at android.app.ActivityThread.main(ActivityThread.java:6776) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410) 

最佳答案

您可以按如下方式定义您的AppComponent:

@Singleton
@Component(modules = {AndroidSupportInjectionModule.class, AppBuilder.class, AppModule.class})
interface AppComponent : AndroidInjector<App>

让您的应用使用它:

public class App extends Application implements HasActivityInjector, HasSupportFragmentInjector {

@Inject
DispatchingAndroidInjector<Activity> dispatchingActivityInjector;

@Inject
DispatchingAndroidInjector<Fragment> dispatchingFragmentInjector;

@Override
public void onCreate() {
// Pay attention here: you have to initialize your `AppModule` with the context.
// Without it, Dagger won't be able to provide a `Context`.
// Since your AppDataManager needs a context to be provided, Dagger will also fail to provide it.
DaggerAppComponent.builder()
.appModule(AppModule(this)) // <-- don't forget this line
.build()
.inject(this);
}

@Override
public AndroidInjector<Activity> activityInjector() {
return dispatchingActivityInjector;
}

@Override
public AndroidInjector<Fragment> supportFragmentInjector() {
return dispatchingFragmentInjector;
}
}

您的 AppBuilder 应该如下所示:

@Module
public abstract class AppBuilder {
@ContributesAndroidInjector(modules = {SplashModule.class})
abstract SplashActivity splashActivityInjector();
}

和你的AppModule:

@Module
public class AppModule {
private Context mContext;

public AppModule(Context context) {
mContext = context;
}

@Provides
@Singleton
Context provideContext() {
return mContext;
}

@Provides
@Singleton
AppDataManager provideAppDataManager(Context context) {
return new AppDataManager(context);
}
}

您的SplashModule:

@Module
abstract class SplashModule {

@Binds
abstract SplashContract.View provideView(SplashActivity activity)

@Binds
abstract SplashContract.Presenter providePresenter(SplashPresenter presenter)
}

在演示者中使用构造函数注入(inject):

@Inject
public SplashPresenter(SplashContract.View view, AppDataManager manager) {
mView = view;
mManager = manager;
}

最后使用 @Inject SplashContract.Presenter presenter 将您的演示者注入(inject)到 SplashActivity 中。为此,请确保您的 SplashActivity 扩展了 DaggerAppCompatActivity。此外,SplashActivity 必须实现 SplashContract.ViewSplashPresenter 必须实现 SplashContract.Presenter

如果您的 AppComponent 未声明为 Singleton,则每次注入(inject) AppDataManager 时都会有一个不同的实例。用 @Singleton 标记它可以确保只要提供它的组件处于 Activity 状态,您就会收到相同的对象。由于您的 AppComponent 与您的 Application 相关联,因此您的组件不会消亡,因此会提供相同的对象实例。

根据经验,您应该尽可能使用构造函数注入(inject)。通过使用它,Dagger 将注入(inject)创建对象所需的每个参数。此外,使用 @Inject 标记构造函数使其成为依赖关系图的一部分:现在无需创建 @Provides 方法即可注入(inject)它。

您必须手动初始化 AppModule,因为它使用非空构造函数。此时,Dagger 不知道如何提供 Context(用于创建您的 AppModule)。如果安装在 AppComponent 上的模块使用默认的空构造函数,则您不必自己对其进行初始化。

@Binds 注释用于进一步减少样板文件。它必须应用于具有单个参数的抽象函数,该参数的类型可分配给返回类型。在您的情况下,参数 SplashScreenActivity 实现了返回类型 SplashContract.View:每当您注入(inject) SplashContract.View 时,Dagger 都会提供接口(interface)实现的 SplashScreenActivity

关于Android Dagger 2.14 设置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49106564/

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