我正在使用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
提供HomeModule
。HomeModule
甚至不应该是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()
}