Kotlin Android MVP + Dagger 2 lateinit property presenter не инициализирован

Попытка использовать Dagger с Kotlin на Android. И получилось исключение:

Caused by: kotlin.UninitializedPropertyAccessException: lateinit property presenter has not been initialized
    at com.ad.eartquakekotlin.main.MainFragment.onViewCreated(MainFragment.kt:43)
    at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1471)
    at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1784)
    at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1852)
    at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:802)
    at ...

Приложение специально предназначено для тестирования. Я получаю землетрясения и показываю их на экране устройства.

Все, что я хочу, это 1. Вставить докладчика в мой фрагмент (просмотр) 2. Внедрить api в моего докладчика

Вот структура моего проекта:

Kotlin Android MVP + Dagger 2 lateinit property presenter не инициализирован

Как видите, там два модуля и компонентов:

@Module
class ApplicationModule(private val application: Application) {
    @Provides
    @Singleton
    fun provideApplication():Application = application
}

@Module
class MainModule (private val view: MainContract.View) {
    @Provides
    fun provideView(): MainContract.View {
        return view
    }

    @Provides
    fun providePresenter(): MainContract.Presenter {
        return MainPresenter(view)
    }
}

И компоненты:

@Component(modules = [ApplicationModule::class])
interface ApplicationComponent {
    fun inject(application: Application)
    fun plus (mainModule: MainModule) : MainComponent
}

а также

@Subcomponent(modules = [MainModule::class])
interface MainComponent {
    fun inject (view : MainContract.View)
}

Есть договор:

interface MainContract {
interface View {
    fun showLoading()
    fun hideLoading()
    fun showMessage(message: String)
    fun showData(data: EarthquakeRootObject)

}
interface Presenter {
    fun onDestroy()
    fun loadData()
}
}

Класс приложения:

class MainApp: Application() {

companion object {
    lateinit var graph: ApplicationComponent
}

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

private fun buildGraph() {
    graph = DaggerApplicationComponent
            .builder()
            .applicationModule(ApplicationModule(this))
            .build()
}
}

Фрагмент (где я хочу использовать инъекцию)

class MainFragment : Fragment(), MainContract.View {

private lateinit var earthquakesAdapter: EarthquakeRecyclerViewAdapter
private lateinit var earthquakes: EarthquakeRootObject
@Inject lateinit var presenter: MainContract.Presenter

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

override fun onAttach(context: Context?) {
    super.onAttach(context)
    MainApp.graph.plus(MainModule(this)).inject(this)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    earthquakesRecyclerView.layoutManager = LinearLayoutManager(context)
    earthquakesRecyclerView.setHasFixedSize(true)

    presenter.loadData()
}

И мой ведущий

class MainPresenter (var view: MainContract.View?) : MainContract.Presenter {

private var disposable: Disposable? = null
@Inject lateinit var api : EarthquakeApi

override fun onDestroy() {
    disposable?.dispose()
    view = null
}

override fun loadData() {
    view?.showLoading()

    disposable = api.getEarthquakes()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(
                    {
                        response ->
                        view?.showData(response)
                        view?.hideLoading()
                    },
                    {
                        throwable ->
                        view?.showMessage(throwable.message ?: "Ошибка")
                        view?.hideLoading()
                    }
            )
}

Что я делаю не так?

Код MainComponent, который является наиболее важным файлом для этого вопроса, отсутствует.

EpicPandaForce 09.10.2018 13:59

@EpicPandaForce обновлен, спасибо.

Oleg Skidan 09.10.2018 14:02
0
2
1 233
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вам нужно заменить

fun inject (view : MainContract.View)

с участием

fun inject(target : MainFragment)

Спасибо. Но то же самое исключение, которое я получил глубже, в презентаторе 'lateinit property api не инициализировано'. Мне нужно сделать там component.inject ()?

Oleg Skidan 09.10.2018 15:43

Фактически, вам здесь не хватает class MainPresenter @Inject constructor(val view, и переменная @Inject lateinit не нужна.

EpicPandaForce 09.10.2018 16:21

Другие вопросы по теме