科特林+;匕首注入问题取决于设备';s Android版本/SDK(?)

科特林+;匕首注入问题取决于设备';s Android版本/SDK(?),android,kotlin,dagger-2,dagger,kapt,Android,Kotlin,Dagger 2,Dagger,Kapt,上周,在我当前的Kotlin MVP项目中实施Dagger时, 由于主手机的维护,我用KitKat在旧手机上测试它(是的,它仍然支持所有主要的材料功能和材料:))。 所以那一周我遇到了一些典型的问题,而不是一些不寻常的问题,并且通过调查提供的错误或多或少地很快地解决了这些问题。 最后,经过代码编译,当前的项目版本在KitKat上构建时没有问题,运行时没有主要的bug,UI交互 但当我从维修中心拿着装有牛轧糖(Nougat)7.1.2的主手机并在上面启动应用程序时,我遇到了奇怪的DI相关问题。就在

上周,在我当前的Kotlin MVP项目中实施Dagger时, 由于主手机的维护,我用KitKat在旧手机上测试它(是的,它仍然支持所有主要的材料功能和材料:))。 所以那一周我遇到了一些典型的问题,而不是一些不寻常的问题,并且通过调查提供的错误或多或少地很快地解决了这些问题。 最后,经过代码编译,当前的项目版本在KitKat上构建时没有问题,运行时没有主要的bug,UI交互

但当我从维修中心拿着装有牛轧糖(Nougat)7.1.2的主手机并在上面启动应用程序时,我遇到了奇怪的DI相关问题。就在那之后 我还在mate的棉花糖6.0上发布了一个应用程序,又抓到了一个,完全一样。 以下简要描述了该问题:

  • 应用程序(成功)启动

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

  • 所有服务也可用,并按预期通过注入运行

  • 当我抽搐活动的演示者时,应用程序崩溃

现在最有趣的部分让我抓狂:所有可访问的类都被注入,它们不会带来任何问题 构造函数注入

但是使用字段注入注入的Presenter实例在需要时未初始化

当然,我试着不使用lateinit修饰符,而是像使用@JvmField或不使用它的nullable字段一样注入它:结果是一样的——根本不注入它

由于该问题与
活动相关,我有一个“自然约束”不使用主构造函数进行注入

这里是一个例外,除了第一个字符串外,它对我来说不是很有用:

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<Activity>? = null

    override fun onCreate() {
        super.onCreate()
        DaggerMyAppComponent.builder().create(this).inject(this)
    }

    override fun activityInjector(): AndroidInjector<Activity>? {
        return activityInjector
    }
}
@Singleton
@Component(modules = [
    MyAppModule::class,
    DataModule::class,
    PreferencesModule::class,
    ServiceModule::class,
    NavigationModule::class
])
interface MyAppComponent : AndroidInjector<MyApp> {

    @Component.Builder
    abstract class Builder : AndroidInjector.Builder<MyApp>()
}
@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
}
@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
        }
    }
}
abstract class BaseActivity : AppCompatActivity(), HasSupportFragmentInjector {

    @Inject
    @field:Named(BaseActivityModule.ACTIVITY_FRAGMENT_MANAGER)
    lateinit var fragmentManager: FragmentManager

    @Inject
    lateinit var fragmentInjector: DispatchingAndroidInjector<Fragment>

    override fun onCreate(@Nullable savedInstanceState: Bundle?) {
        AndroidInjection.inject(this)
        super.onCreate(savedInstanceState)
    }

    override fun supportFragmentInjector(): AndroidInjector<Fragment>? {
        return fragmentInjector
    }
}
基本活动模块:

class MyApp : MultiDexApplication(), HasActivityInjector {

    @Inject
    @JvmField
    var activityInjector: DispatchingAndroidInjector<Activity>? = null

    override fun onCreate() {
        super.onCreate()
        DaggerMyAppComponent.builder().create(this).inject(this)
    }

    override fun activityInjector(): AndroidInjector<Activity>? {
        return activityInjector
    }
}
@Singleton
@Component(modules = [
    MyAppModule::class,
    DataModule::class,
    PreferencesModule::class,
    ServiceModule::class,
    NavigationModule::class
])
interface MyAppComponent : AndroidInjector<MyApp> {

    @Component.Builder
    abstract class Builder : AndroidInjector.Builder<MyApp>()
}
@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
}
@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
        }
    }
}
abstract class BaseActivity : AppCompatActivity(), HasSupportFragmentInjector {

    @Inject
    @field:Named(BaseActivityModule.ACTIVITY_FRAGMENT_MANAGER)
    lateinit var fragmentManager: FragmentManager

    @Inject
    lateinit var fragmentInjector: DispatchingAndroidInjector<Fragment>

    override fun onCreate(@Nullable savedInstanceState: Bundle?) {
        AndroidInjection.inject(this)
        super.onCreate(savedInstanceState)
    }

    override fun supportFragmentInjector(): AndroidInjector<Fragment>? {
        return fragmentInjector
    }
}
目前我有一个分支广泛的MVP模型,所以每个活动/片段都有一个视图模块和一个演示者模块,以及所有常见的注入 通过基类进行交互。以下是活动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
}
基本活动:

class MyApp : MultiDexApplication(), HasActivityInjector {

    @Inject
    @JvmField
    var activityInjector: DispatchingAndroidInjector<Activity>? = null

    override fun onCreate() {
        super.onCreate()
        DaggerMyAppComponent.builder().create(this).inject(this)
    }

    override fun activityInjector(): AndroidInjector<Activity>? {
        return activityInjector
    }
}
@Singleton
@Component(modules = [
    MyAppModule::class,
    DataModule::class,
    PreferencesModule::class,
    ServiceModule::class,
    NavigationModule::class
])
interface MyAppComponent : AndroidInjector<MyApp> {

    @Component.Builder
    abstract class Builder : AndroidInjector.Builder<MyApp>()
}
@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
}
@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
        }
    }
}
abstract class BaseActivity : AppCompatActivity(), HasSupportFragmentInjector {

    @Inject
    @field:Named(BaseActivityModule.ACTIVITY_FRAGMENT_MANAGER)
    lateinit var fragmentManager: FragmentManager

    @Inject
    lateinit var fragmentInjector: DispatchingAndroidInjector<Fragment>

    override fun onCreate(@Nullable savedInstanceState: Bundle?) {
        AndroidInjection.inject(this)
        super.onCreate(savedInstanceState)
    }

    override fun supportFragmentInjector(): AndroidInjector<Fragment>? {
        return fragmentInjector
    }
}
但是,正如前面所说,KitKat上并没有发生这种情况——应用程序在它上面运行没有任何问题。所以,再一次:我认为问题是存在的 当应用程序在棉花糖+上运行时(不幸的是,我还不知道棒棒糖)

我真的很想知道以前是否有经验丰富的人有过这样的问题。没有构建错误,没有匕首异常;只是未初始化的属性

这可能与许可证有某种关系吗?我唯一的危险许可是设备的定位权限,它已经被持有并测试过了

毕竟,如果存在支持/版本控制问题的可能性,那么它还与哪些方面相关呢

提前谢谢

UPD:

class MyApp : MultiDexApplication(), HasActivityInjector {

    @Inject
    @JvmField
    var activityInjector: DispatchingAndroidInjector<Activity>? = null

    override fun onCreate() {
        super.onCreate()
        DaggerMyAppComponent.builder().create(this).inject(this)
    }

    override fun activityInjector(): AndroidInjector<Activity>? {
        return activityInjector
    }
}
@Singleton
@Component(modules = [
    MyAppModule::class,
    DataModule::class,
    PreferencesModule::class,
    ServiceModule::class,
    NavigationModule::class
])
interface MyAppComponent : AndroidInjector<MyApp> {

    @Component.Builder
    abstract class Builder : AndroidInjector.Builder<MyApp>()
}
@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
}
@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
        }
    }
}
abstract class BaseActivity : AppCompatActivity(), HasSupportFragmentInjector {

    @Inject
    @field:Named(BaseActivityModule.ACTIVITY_FRAGMENT_MANAGER)
    lateinit var fragmentManager: FragmentManager

    @Inject
    lateinit var fragmentInjector: DispatchingAndroidInjector<Fragment>

    override fun onCreate(@Nullable savedInstanceState: Bundle?) {
        AndroidInjection.inject(this)
        super.onCreate(savedInstanceState)
    }

    override fun supportFragmentInjector(): AndroidInjector<Fragment>? {
        return fragmentInjector
    }
}
似乎presenter实例在其
onCreate()
之后立即绑定到
活动
,但是取消绑定是在触发了一些以侦听器角色包含活动的回调操作时。所以,看起来Kotlin再次查找presenter,但发现它未初始化。仍然不明白为什么这只发生在更新的平台上