Kotlin + Dagger注入问题取决于设备的Android版本/ SDK(?)

上周,在我现在的Kotlin MVP项目中实施Dagger的时候,我正在使用KitKat 4.4.2在老式手机上进行测试(因为主要手机的维护,它仍然支持所有主要的function和东西)。 所以那一周我遇到了一些典型的问题,而不是一些不寻常的事情,通过调查提供的错误,或多或少地快速解决问题 终于,代码编译,当前的项目版本建成没有问题,没有运行与UI交互KitKat的重大错误。

但是,当我从维修中心拿走了带有Nougat 7.1.2的主电话并启动了应用程序时,我陷入了奇怪的DI相关问题。 之后,我也在mate的Marshmallow 6.0上推出了应用程序,并且又抓了一个,完全一样。 这个问题简单描述如下:

  • 应用程序(成功)启动;

  • 我能够操作通过上下文和fragmentManager注入提供的ViewPager / DrawerLayout / etc uifunction;

  • 所有的服务也可以按照预期的方式进行注射。

  • 当我抽动Activity的Presenter时,应用程序崩溃。

而现在最有趣的部分,这让我疯狂:所有可访问的类,不带来任何问题,通过构造注入注入。

但是,使用字段注入注入的Presenter实例在需要时不会被初始化

当然,我试图不使用lateinit修饰符,并注入它像@JvmField可空字段或没有它:结果是相同的 – 它根本不被注入。

由于问题与Activity有关,我有“自然约束”不使用主要构造函数注入。

这是一个例外情况,除了第一个字符串外,对我来说不是很有帮助。

 kotlin.UninitializedPropertyAccessException: lateinit property presenter has not been initialized at .ui.common.view.BaseViewActivity.getPresenter(BaseViewActivity.kt:14) at .ui.main.view.MainActivity.onPlaceTypeClick(MainActivity.kt:143) at .ui.types.nearby.view.NearbyPlaceTypeItemViewHolder$bind$1.onClick(NearbyPlaceTypeItemViewHolder.kt:32) at android.view.View.performClick(View.java:5647) at android.view.View$PerformClick.run(View.java:22462) at android.os.Handler.handleCallback(Handler.java:754) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:163) at android.app.ActivityThread.main(ActivityThread.java:6205) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794) 

这里是一些代码:

应用程序:

 class MyApp : MultiDexApplication(), HasActivityInjector { @Inject @JvmField var activityInjector: DispatchingAndroidInjector? = null override fun onCreate() { super.onCreate() DaggerMyAppComponent.builder().create(this).inject(this) } override fun activityInjector(): AndroidInjector? { return activityInjector } } 

AppComponent:

 @Singleton @Component(modules = [ MyAppModule::class, DataModule::class, PreferencesModule::class, ServiceModule::class, NavigationModule::class ]) interface MyAppComponent : AndroidInjector { @Component.Builder abstract class Builder : AndroidInjector.Builder() } 

的AppModule:

 @Module(includes = [AndroidSupportInjectionModule::class]) abstract class MyAppModule { @Binds @Singleton abstract fun application(myApp: MyApp): Application @PerActivity @ContributesAndroidInjector(modules = [(MainActivityModule::class)]) abstract fun mainActivityInjector(): MainActivity //... other activity injectors } 

BaseActivityModule:

 @Module abstract class BaseActivityModule { @Binds @PerActivity internal abstract fun activity(appCompatActivity: AppCompatActivity): Activity @Binds @PerActivity internal abstract fun activityContext(activity: Activity): Context @Module companion object { const val ACTIVITY_FRAGMENT_MANAGER = "BaseActivityModule.activityFragmentManager" @JvmStatic @Provides @Named(ACTIVITY_FRAGMENT_MANAGER) @PerActivity fun activityFragmentManager(activity: AppCompatActivity): FragmentManager { return activity.supportFragmentManager } } } 

目前我有一个宽分支MVP模型,所以每个活动/片段有1个视图模块和1个演示模块,所有常见的注射交互通过基类。 以下是Activity DI部分的示例:

 @Module(includes = [ BaseActivityModule::class, MainPresenterModule::class ]) abstract class MainActivityModule { @Binds @PerActivity abstract fun mainView(mainActivity: MainActivity): MainView @Binds @PerActivity abstract fun appCompatActivity(mainActivity: MainActivity): AppCompatActivity @PerFragment @ContributesAndroidInjector(modules = [LocationFragmentModule::class]) abstract fun locationFragmentInjector(): LocationFragment //... other related fragments injection methods } @Module abstract class MainPresenterModule { @Binds @PerActivity abstract fun mainPresenter(mainPresenterImpl: MainPresenterImpl): MainPresenter } 

BaseActivity:

 abstract class BaseActivity : AppCompatActivity(), HasSupportFragmentInjector { @Inject @field:Named(BaseActivityModule.ACTIVITY_FRAGMENT_MANAGER) lateinit var fragmentManager: FragmentManager @Inject lateinit var fragmentInjector: DispatchingAndroidInjector override fun onCreate(@Nullable savedInstanceState: Bundle?) { AndroidInjection.inject(this) super.onCreate(savedInstanceState) } override fun supportFragmentInjector(): AndroidInjector? { return fragmentInjector } } 

使用构造函数注入的示例 – MainPresenter (所有注入工作 – 这里没有问题):

 @PerActivity class MainPresenterImpl @Inject constructor( val navigationManager: NavigationManager, val locationManager: LocationManagerImpl, val sharedPrefsRepo: SharedPreferencesRepository, view: MainActivity) : BaseViewPresenter(view), MainPresenter { } 

下面是所有“魔术”开始地方var presenter在任何情况下都不会初始化。

 abstract class BaseViewActivity (): BaseActivity(), MVPView { @Inject lateinit var presenter: T } 

但是,正如所说,这不是发生在KitKat – 应用程序正在运行没有任何问题。 所以,再一次:我认为应用程序运行在棉花糖上时存在问题+ (不幸的是,还不知道棒棒糖)。

我真的很怀疑过去有没有人遇到这样的问题。 没有建立错误,没有匕首的例外; 只是非初始化的财产。

它可能与某些方面的权限有关吗? 我拥有的唯一的危险许可是设备的位置接入,并且它被保存和测试。

毕竟,如果存在支持/版本问题的可能性,那么它还有什么其他的方面呢?

提前致谢。

UPD:

似乎演示者实例在onCreate()之后被绑定Activity ,但是当触发了Activity中的Activity时, 解除了绑定 。 所以,看起来Kotlin再次看到主持人,但发现它未初始化。 仍然不明白为什么这只发生在新平台上。