【问题标题】:Dagger2 Android DI - lateinit property has not been initializedDagger2 Android DI - lateinit 属性尚未初始化
【发布时间】:2020-09-23 19:23:48
【问题描述】:

我正在使用 Dagger2 进行 DI 项目。我在 MVP 架构中注入演示者。 由于某种原因,当我构建应用程序时,它会因错误而崩溃: “lateinit 属性演示者尚未初始化”。我知道这意味着没有进行注射,但我不明白为什么。这是我的代码:

应用类

class FlowerApp : Application() {

override fun onCreate() {
    super.onCreate()
    initAppComponent()
}

private fun initAppComponent() {
    appComponent = DaggerAppComponent
        .builder()
        .appModule(AppModule(this))
        .build()
}

companion object {
    lateinit var appComponent: AppComponent
}
 }

家庭模块

@Module
class HomeModule(var homeFragment: HomeContract.View) {
    @Provides
    fun providePresenter(homeInteractor: HomeInteractor): HomePresenter {
        return HomePresenter(homeFragment, homeInteractor)
    }

    @Provides
    fun provideInteractor(): HomeInteractor {
        return HomeInteractor()
    }
}

应用组件

 @Component(
    modules = [
        (AppModule::class),
        (NetworkModule::class),
        (HomeModule::class)
    ]
)

interface AppComponent {
    fun inject(application: FlowerApp)
    fun inject(homeFragment: HomeContract.View)
}

家庭片段

class HomeFragment : Fragment(), HomeContract.View {
    @Inject
    lateinit var presenter: HomePresenter
    private lateinit var flowerAdapter: FlowerAdapter
    private var startingPage = 1
    private var recyclerStartPos = 0

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_home, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        setAdapter()
        presenter.getFlowers(startingPage)
        setListeners()
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        FlowerApp.appComponent.inject(this)
    }

如果需要有关代码的任何其他信息,请询问...

已编辑:logcat 错误:

2020-06-06 22:12:37.513 13401-13401/? E/AndroidRuntime: 致命异常: main 进程:element.list.flowersmvp,PID:13401 kotlin.UninitializedPropertyAccessException:lateinit 属性展示器尚未初始化 在 element.list.flowersmvp.home.HomeFragment.onViewCreated(HomeFragment.kt:37) 在 androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:892) 在 androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManagerImpl.java:1238) 在 androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:1303) 在 androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:439) 在 androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManagerImpl.java:2079) 在 androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManagerImpl.java:1869) 在 androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManagerImpl.java:1824) 在 androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManagerImpl.java:1727) 在 androidx.fragment.app.FragmentManagerImpl.dispatchStateChange(FragmentManagerImpl.java:2663) 在 androidx.fragment.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManagerImpl.java:2613) 在 androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:246) 在 androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:542) 在 androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:201) 在 android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1392) 在 android.app.Activity.performStart(Activity.java:7252) 在 android.app.ActivityThread.handleStartActivity(ActivityThread.java:2970) 在 android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:180) 在 android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:165) 在 android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:142) 在 android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70) 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1831) 在 android.os.Handler.dispatchMessage(Handler.java:106) 在 android.os.Looper.loop(Looper.java:201) 在 android.app.ActivityThread.main(ActivityThread.java:6806) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)

【问题讨论】:

  • 这可能会有所帮助:stackoverflow.com/questions/54288418/…
  • 在此处发布您的 logcat 错误
  • 你去,我编辑了问题
  • HomeFragmentonCreate() 中尝试调用FlowerApp.appComponent.inject(this) 之前 super.onCreate(savedInstanceState)
  • 它没有帮助

标签: android kotlin dagger-2


【解决方案1】:

您正试图通过应用程序的主要组件注入HomeModule 中提供的演示者。这行不通,因为您从未将HomeModule 提供给您的AppComponentHomeModule 甚至不应该是 AppComponent 的一部分,因为它提供的东西(演示者和交互者)仅在片段存在时才存在,这意味着它们存在于片段范围内,而不是应用程序范围内。

您需要做的是创建另一个将注入您的片段的组件,例如

@Component(
    modules = [
        (HomeModule::class)
    ]
)
interface HomeComponent {
    fun inject(homeFragment: HomeFragment)
}

然后在你的HomeFragment:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    DaggerHomeComponent
        .builder()
        .homeModule(HomeModule(this))
        .build()
        .inject(this)
}

如果您需要应用程序范围内的东西(来自网络和应用程序模块),那么您可以像以前一样通过AppComponent 注入它们。

【讨论】:

    【解决方案2】:

    我认为问题出在您 HomeModule 中的 var homeFragment: HomeContract.View 中。我建议你重写 HomePresenter 并将通过构造函数传递 HomeFragment 替换为方法 bindView/unbindView。

    class HomePresenter(private val interactor: HomeInteractor) {
        var view: HomeView? = null
    
        fun bindView(view: HomeView) {
            this.view = view
        }
    
        fun unbindView() {
            view = null
        }
    }
    

    在 Fragment 已销毁且 Presenter 未销毁的情况下,将 Fragment 引用存储在 Presenter 中可能会导致内存泄漏和空指针异常。

    【讨论】:

    • var homeFragment: HomeContract.View 实际上不是片段引用。它是 HomeContract 类的接口(MVP 的一部分)。我真正的片段 HomeFragment 只知道它需要覆盖哪些方法。所以这个建议没有意义。不过还是谢谢...
    • 那个“接口”实际上是一个片段引用。这样做很可能会导致内存泄漏或崩溃。
    • 嗯,这很奇怪。我从我的优秀 teamLead 的项目中得到了这种方式,我认为该项目的质量非常高。好的,我会改变它。所以@EpicPandaForce 你认为这真的可能是 dagger2 不工作的原因吗?
    • 您应该始终(好吧,尝试始终:p)测试您的应用在内存不足的情况下是否可以在任何屏幕上运行。您可以在此处查看如何测试:stackoverflow.com/questions/49046773/… 在您的情况下,如果您在不使用 findFragmentByTag 的情况下传递片段引用,您将获得 NPE,或者您将获得重叠片段。
    • 好的,谢谢。但这对 Dagger2 错误和这个问题没有帮助。你知道怎么解决吗?
    【解决方案3】:

    在您的组件中,您注入的不是HomeFragment,而是基类(HomeContract.View)。这意味着 Dagger 不会注入不在基类中的 HomeFragment 的属性。

    【讨论】:

    • 是的,但是如果我将 Appcompnent 更改为使用 HomeFragment 而不是 HomeContract.View 它仍然会崩溃
    【解决方案4】:

    我认为问题所在,你没有注入HomeFragment

    在 AppComponent 中添加扩展方法

    @Component(
        modules = [
            (AppModule::class),
            (NetworkModule::class),
            (HomeModule::class)
        ]
    )
    
    interface AppComponent {
        fun inject(application: FlowerApp)
        fun inject(homeFragment: HomeContract.View)
    }
    
    fun HomeFragment.inject(){
        FlowApp.appComponent.inject(this)
    }
    

    注入 HomeFragment

    override fun onAttach(context: Context) {
            super.onAttach(context)
            inject()
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-25
      • 1970-01-01
      • 1970-01-01
      • 2022-11-22
      • 2017-03-03
      • 1970-01-01
      • 1970-01-01
      • 2020-12-31
      相关资源
      最近更新 更多