Dagger2 Android DI - lateinit 属性尚未初始化



我正在使用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)
}

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

已编辑:日志猫错误:

2020-06-06 22:12:37.513 13401-13401/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: element.list.flowersmvp, PID: 13401
kotlin.UninitializedPropertyAccessException: lateinit property presenter has not been initialized
at element.list.flowersmvp.home.HomeFragment.onViewCreated(HomeFragment.kt:37)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:892)
at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManagerImpl.java:1238)
at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:1303)
at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:439)
at androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManagerImpl.java:2079)
at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManagerImpl.java:1869)
at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManagerImpl.java:1824)
at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManagerImpl.java:1727)
at androidx.fragment.app.FragmentManagerImpl.dispatchStateChange(FragmentManagerImpl.java:2663)
at androidx.fragment.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManagerImpl.java:2613)
at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:246)
at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:542)
at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:201)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1392)
at android.app.Activity.performStart(Activity.java:7252)
at android.app.ActivityThread.handleStartActivity(ActivityThread.java:2970)
at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:180)
at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:165)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:142)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:70)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1831)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:201)
at android.app.ActivityThread.main(ActivityThread.java:6806)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)

您正在尝试通过应用程序的主组件注入HomeModule中提供的演示器。这不起作用,因为您从未向AppComponent提供HomeModuleHomeModule甚至不应该是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注入它们。

我认为问题出在您的家庭模块中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
}
}

在演示器中存储片段引用可能会导致内存泄漏和空指针异常,前提是片段已销毁而演示器未销毁。

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

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

在应用组件中添加扩展方法

@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)
}

注入主页片段

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

最新更新