Djek-Grif
Djek-Grif

Reputation: 1546

Is there any way to use Koin inject with generic?

I heve base class and I would like to use Koin injection on this base class like:

abstract class BasePresenterFragment<T : BasePresenter> : BaseFragment() {

    lateinit var presenter: T by inject<T>() // here is problem

    override fun onStart() {
        super.onStart()
        presenter.subscribe()
    }

    override fun onStop() {
        super.onStop()
        presenter.unSubscribe()
    }
} 

I know there are solutions for inject viewModel but not for simple injection. So is there any way to use Koin injection with generic type?

Upvotes: 3

Views: 4105

Answers (3)

Adnan Abdollah Zaki
Adnan Abdollah Zaki

Reputation: 4406

the short answer is Yes

if you have generic classes like this :

the interface :

interface UseCase<Input, Output> {
    suspend operator fun invoke(input: Input): Output
}

class implement interface :

class UpdateMovieUseCase internal constructor(
    private val repository: MovieRepository
) : UseCase<MovieDomainModel, Unit> {
    override suspend fun invoke(movie: MovieDomainModel) =
        repository.update(movie.toData())
}

then you can provide a module in KOIN like this :

val domainModule = module {
    singleOf(::UpdateMovieUseCase) { bind<UseCase<MovieDomainModel, Unit>>() }
}

source code : https://github.com/Adnan9011/movie_archive

Upvotes: 2

r-hold
r-hold

Reputation: 1120

Koin does not support generics by default.

"Koin definitions doesn't take in accounts generics type argument."

however you are supposed to you the named argument to workaround this:

The latest Version even supports directly passing the type insted of a custom string:

module {
  single(named<Int>) { ArrayList<Int>() }
  single(named<String>) { ArrayList<String>() }
}

and when injecting, simply use get(named<Int>) or get(named<String>) depending on your need. For more information cf.: https://insert-koin.io/docs/reference/koin-core/definitions/

Upvotes: 1

Djek-Grif
Djek-Grif

Reputation: 1546

Well, I've found only partly solution for this question. It's use presenter like abstract val in base class. This will make it possible to use the methods of presenter in the base class but I still should use inject() in every subclasses for initialization. Example:

abstract class BasePresenterFragment<P : BasePresenter> : BaseFragment() {

    abstract val presenter: P

    override fun onStart() {
        super.onStart()
        presenter.subscribe()
    }

    override fun onStop() {
        super.onStop()
        presenter.unSubscribe()
    }
}

And subclass:

class HomeFragment : BasePresenterFragment<HomeContract.Presenter>(), HomeContract.View {
     ...
     override val presenter: HomeContract.Presenter by inject()
     ...
}

Upvotes: 4

Related Questions