I'm learning Koin right now and here is my trouble.
When I'm trying to run a application, I am getting this error:
kt:23)
at com.example.radioapp.ModulesKt$appModule$1$3.invoke(Modules.kt:15)
at org.koin.core.instance.InstanceFactory.create(InstanceFactory.kt:53)
at org.koin.core.instance.FactoryInstanceFactory.get(FactoryInstanceFactory.kt:38)
at org.koin.core.registry.InstanceRegistry.resolveInstance$koin_core(InstanceRegistry.kt:110)
at org.koin.core.scope.Scope.resolveValue(Scope.kt:254)
at org.koin.core.scope.Scope.resolveInstance(Scope.kt:241)
at org.koin.core.scope.Scope.get(Scope.kt:204)
at com.example.radioapp.ModulesKt$appModule$1$4.invoke(Modules.kt:23)
at com.example.radioapp.ModulesKt$appModule$1$4.invoke(Modules.kt:16)
at org.koin.core.instance.InstanceFactory.create(InstanceFactory.kt:53)
at org.koin.core.instance.FactoryInstanceFactory.get(FactoryInstanceFactory.kt:38)
at org.koin.core.registry.InstanceRegistry.resolveInstance$koin_core(InstanceRegistry.kt:110)
at org.koin.core.scope.Scope.resolveValue(Scope.kt:254)
at org.koin.core.scope.Scope.resolveInstance(Scope.kt:241)
at org.koin.core.scope.Scope.get(Scope.kt:204)
at com.example.radioapp.coordinators.RadioStations.<init>(RadioStations.kt:130)
at com.example.radioapp.ModulesKt$appModule$1$1.invoke(Modules.kt:13)
at com.example.radioapp.ModulesKt$appModule$1$1.invoke(Modules.kt:13)
at org.koin.core.instance.InstanceFactory.create(InstanceFactory.kt:53)
at org.koin.core.instance.SingleInstanceFactory.create(SingleInstanceFactory.kt:46)
at org.koin.core.instance.SingleInstanceFactory$get$1.invoke(SingleInstanceFactory.kt:53)
at org.koin.core.instance.SingleInstanceFactory$get$1.invoke(SingleInstanceFactory.kt:51)
at org.koin.mp.KoinPlatformTools.synchronized(PlatformToolsJVM.kt:20)
at org.koin.core.instance.SingleInstanceFactory.get(SingleInstanceFactory.kt:51)
at org.koin.core.registry.InstanceRegistry.resolveInstance$koin_core(InstanceRegistry.kt:110)
at org.koin.core.scope.Scope.resolveValue(Scope.kt:254)
at org.koin.core.scope.Scope.resolveInstance(Scope.kt:241)
at org.koin.core.scope.Scope.get(Scope.kt:204)
at com.example.radioapp.ModulesKt$appModule$1$3.invoke(Modules.kt:23)
at com.example.radioapp.ModulesKt$appModule$1$3.invoke(Modules.kt:15)
at org.koin.core.instance.InstanceFactory.create(InstanceFactory.kt:53)
at org.koin.core.instance.FactoryInstanceFactory.get(FactoryInstanceFactory.kt:38)
at org.koin.core.registry.InstanceRegistry.resolveInstance$koin_core(InstanceRegistry.kt:110)
at org.koin.core.scope.Scope.resolveValue(Scope.kt:254)
at org.koin.core.scope.Scope.resolveInstance(Scope.kt:241)
at org.koin.core.scope.Scope.get(Scope.kt:204)
at com.example.radioapp.ModulesKt$appModule$1$4.invoke(Modules.kt:23)
at com.example.radioapp.ModulesKt$appModule$1$4.invoke(Modules.kt:16)
at org.koin.core.instance.InstanceFactory.create(InstanceFactory.kt:53)
at org.koin.core.instance.FactoryInstanceFactory.get(FactoryInstanceFactory.kt:38)
at org.koin.core.registry.InstanceRegistry.resolveInstance$koin_core(InstanceRegistry.kt:110)
at org.koin.core.scope.Scope.resolveValue(Scope.kt:254)
at org.koin.core.scope.Scope.resolveInstance(Scope.kt:241)
at org.koin.core.scope.Scope.get(Scope.kt:204)
at com.example.radioapp.coordinators.RadioStations.<init>(RadioStations.kt:130)
at com.example.radioapp.ModulesKt$appModule$1$1.invoke(Modules.kt:13)
at com.example.radioapp.ModulesKt$appModule$1$1.invoke(Modules.kt:13)
at org.koin.core.instance.InstanceFactory.create(InstanceFactory.kt:53)
at org.koin.core.instance.SingleInstanceFactory.create(SingleInstanceFactory.kt:46)
at org.koin.core.instance.SingleInstanceFactory$get$1.invoke(SingleInstanceFactory.kt:53)
(yes, this is my log, the beginning of the message was truncated because it has 13k lines)
This application is a streaming app for Belarussian radio listening.
I don't know how to create instance of a ViewModel which is implementing an interface and i'm just need to do this to get the MainFragment context to my ApiImpl class (RadioStations):
RadioStations.kt
interface RadioStationsURLAPI {
fun start(url: String)
fun stop()
fun getURL(id: Int): String
}
class RadioStations : KoinComponent, RadioStationsURLAPI {
private val mp = MediaPlayer()
val context = get<MainFragment>()
private fun getRadioCultureURL(): String {
return URLs.radioCulture
}
private fun getRadioWorldURL(): String {
return URLs.radioWorld
}
private fun getRadioEnergyURL(): String {
return URLs.radioEnergy
}
private fun getRadioCenterURL(): String {
return URLs.radioCenter
}
private fun getRadioOneURL(): String {
return URLs.radioOne
}
private fun getRadioRadiusFmURL(): String {
return URLs.radioRadius
}
private fun getRadioCapitalURL(): String {
return URLs.radioCapital
}
private fun getRadioBelarusURL(): String {
return URLs.radioBelarus
}
private fun getRadioBelarusFmURL(): String {
return URLs.radioBelarusFM
}
private fun getRadioCityFmURL(): String {
return URLs.radioCityFM
}
private fun getRadioMogilevURL(): String {
return URLs.radioMogilev
}
private fun getRadioBaURL(): String {
return URLs.radioBA
}
private fun getRadioRocksURL(): String {
return URLs.radioRocks
}
override fun getURL(id: Int): String {
when (id) {
R.id.radio_item_culture -> return getRadioCultureURL()
R.id.radio_item_world -> return getRadioWorldURL()
R.id.radio_item_energy -> return getRadioEnergyURL()
R.id.radio_item_center -> return getRadioCenterURL()
R.id.radio_item_one -> return getRadioOneURL()
R.id.radio_item_radius -> return getRadioRadiusFmURL()
R.id.radio_item_capital -> return getRadioCapitalURL()
R.id.radio_item_belarus -> return getRadioBelarusURL()
R.id.radio_item_belarus_fm -> return getRadioBelarusFmURL()
R.id.radio_item_city_fm -> return getRadioCityFmURL()
R.id.radio_item_mogilev -> return getRadioMogilevURL()
R.id.radio_item_BA -> return getRadioBaURL()
R.id.radio_item_rocks -> return getRadioRocksURL()
else -> return ""
}
}
override fun start(url: String) {
val uri = Uri.parse(url)
println(uri)
mp.apply {
context.context?.let { setDataSource(it, uri) }
prepareAsync()
}
mp.start()
}
override fun stop() {
mp.stop()
}
}
So here is my Modules.kt for Koin
val appModule = module {
single { RadioStations() }
viewModel { MainViewModel(get()) }
factory<MainViewModelInterface> { MainViewModel(get()) }
fragment { MainFragment(get()) }
}
my MainViewModule.kt
interface MainViewModelInterface {
val choosedRadio: BehaviorSubject<Int>
val recoverableError: PublishSubject<String?>
}
class MainViewModel(val radioStations: RadioStations): ViewModel(), MainViewModelInterface {
override val choosedRadio: BehaviorSubject<Int> = BehaviorSubject.create<Int>()
override val recoverableError: PublishSubject<String?> = PublishSubject.create<String?>()
init {
choosedRadio
.map {
radioStations.getURL(it)
}
.observeOn(Schedulers.newThread())
.doOnError {
recoverableError.onNext(it.localizedMessage)
}
.subscribe({
radioStations.start(it)
}, Timber::e)
}
}
And my MainFragment.kt
class MainFragment(val viewModel: MainViewModelInterface) : Fragment() {
private lateinit var toolbar: androidx.appcompat.widget.Toolbar
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.toolbar_menu, menu)
super.onCreateOptionsMenu(menu, inflater)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_main, container, false)
// Inflate the layout for this fragment
toolbar = view.findViewById(R.id.radio_toolbar)
(requireActivity() as AppCompatActivity).setSupportActionBar(toolbar)
return view
}
override fun onResume() {
super.onResume()
toolbar.setOnMenuItemClickListener {
viewModel.choosedRadio.onNext(it.itemId)
true
}
viewModel.recoverableError
.subscribe {
Toast.makeText(this.context, it, Toast.LENGTH_LONG).show()
}
}
}
How to write instances of my classes in Modules.kt? I've read the Koin documentation but still don't get it how to do this correctly.