Caused by: org.koin.core.error.InstanceCreationException: Could not create instance for [type:Factory,primary_type

19,882

class MainViewModel(newsRepository: Any?) : ViewModel(), CoroutineScope {

Why your newsRepository is of Any? type make it of NewsRepository

class MainViewModel(newsRepository: NewsRepository) : ViewModel(), CoroutineScope {

In app module your NewsRepositoryImpl need's Implementation of SportNewsInterface.

I believe below is missing in your appModule.

factory<SportNewsInterface> { (SportNewsInterfaceImpl()) }

i.e:

val appModules = module {
        // The Retrofit service using our custom HTTP client instance as a singleton
        single {
            createWebService<SportNewsInterface>(
                okHttpClient = createHttpClient(),
                factory = RxJava2CallAdapterFactory.create(),
                baseUrl = BASE_URL
            )
        }
        // Tells Koin how to create an instance of CatRepository
        factory<NewsRepository> { (NewsRepositoryImpl(sportNewsInterface = get())) }

        //Tells Koin how to create SportNewsInterface
        factory<SportNewsInterface> { (SportNewsInterfaceImpl()) }

        // Specific viewModel pattern to tell Koin how to build MainViewModel
        viewModel { MainViewModel (newsRepository = get ())  }
    }

Few other Tip's to clean up your code:

Use ViewModelScope instead of creating your own CoroutineScope in ViewModel

dependency

//Coroutine View Model Scope.
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0"
Share:
19,882
Edgar
Author by

Edgar

Updated on July 06, 2022

Comments

  • Edgar
    Edgar almost 2 years

    I am developing news app I have implemented koin with viewmodel in fragment class but I am getting following error when I test code on emulator

     java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
            at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:557)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:922)
         Caused by: java.lang.reflect.InvocationTargetException
            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:922) 
         Caused by: org.koin.core.error.InstanceCreationException: Could not create instance for [type:Factory,primary_type:'yodgorbek.komilov.musobaqayangiliklari.viewmodel.MainViewModel']
            at org.koin.core.instance.DefinitionInstance.create(DefinitionInstance.kt:61)
            at org.koin.core.instance.FactoryDefinitionInstance.get(FactoryDefinitionInstance.kt:37)
            at org.koin.core.definition.BeanDefinition.resolveInstance(BeanDefinition.kt:70)
            at org.koin.core.scope.Scope.resolveInstance(Scope.kt:165)
            at org.koin.core.scope.Scope.get(Scope.kt:128)
            at org.koin.androidx.viewmodel.ViewModelResolutionKt$createViewModelProvider$1.create(ViewModelResolution.kt:66)
            at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:164)
            at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:130)
            at org.koin.androidx.viewmodel.ViewModelResolutionKt.getInstance(ViewModelResolution.kt:43)
            at org.koin.androidx.viewmodel.ViewModelResolutionKt.getViewModel(ViewModelResolution.kt:23)
            at org.koin.androidx.viewmodel.ext.android.LifecycleOwnerExtKt.getViewModel(LifecycleOwnerExt.kt:85)
            at yodgorbek.komilov.musobaqayangiliklari.ui.TopHeadlinesFragment$$special$$inlined$viewModel$1.invoke(LifecycleOwnerExt.kt:95)
            at yodgorbek.komilov.musobaqayangiliklari.ui.TopHeadlinesFragment$$special$$inlined$viewModel$1.invoke(Unknown Source:0)
            at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
            at yodgorbek.komilov.musobaqayangiliklari.ui.TopHeadlinesFragment.getViewModel(Unknown Source:7)
            at yodgorbek.komilov.musobaqayangiliklari.ui.TopHeadlinesFragment.initViewModel(TopHeadlinesFragment.kt:57)
            at yodgorbek.komilov.musobaqayangiliklari.ui.TopHeadlinesFragment.onCreateView(TopHeadlinesFragment.kt:51)
            at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2600)
            at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:881)
            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:3000)
            at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:185)
            at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:170)
    2019-11-16 15:12:01.728 12995-12995/yodgorbek.komilov.musobaqayangiliklari E/AndroidRuntime:     at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:147)
            at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:73)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1858)
            at android.os.Handler.dispatchMessage(Handler.java:106)
            at android.os.Looper.loop(Looper.java:201)
            at android.app.ActivityThread.main(ActivityThread.java:6820)
                ... 3 more
         Caused by: org.koin.core.error.NoBeanDefFoundException: No definition found for 'java.lang.Object' has been found. Check your module definitions.
            at org.koin.core.scope.Scope.findDefinition(Scope.kt:170)
            at org.koin.core.scope.Scope.resolveInstance(Scope.kt:164)
            at org.koin.core.scope.Scope.get(Scope.kt:128)
            at yodgorbek.komilov.musobaqayangiliklari.di.application.module.AppModulesKt$appModules$1$3.invoke(appModules.kt:65)
            at yodgorbek.komilov.musobaqayangiliklari.di.application.module.AppModulesKt$appModules$1$3.invoke(Unknown Source:4)
            at org.koin.core.instance.DefinitionInstance.create(DefinitionInstance.kt:54)
                ... 44 more
    

    below TopHeadlinesFragment.kt

    class TopHeadlinesFragment : Fragment() {

    private val viewModel: MainViewModel by viewModel()
    private lateinit var topHeadlinesAdapter: TopHeadlinesAdapter
    
    
    //3
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(
            R.layout.fragment_top_headlines
            , container, false
        )
    
    
        val recyclerView = view.findViewById(R.id.recyclerView) as RecyclerView
        val pb = view.findViewById(R.id.pb) as ProgressBar
        topHeadlinesAdapter = TopHeadlinesAdapter(recyclerView.context)
        recyclerView.layoutManager = LinearLayoutManager(context)
        recyclerView.adapter = topHeadlinesAdapter
        initViewModel()
    
        return view
    }
    
    private fun initViewModel() {
        viewModel?.sportList?.observe(this, Observer { newList ->
            topHeadlinesAdapter.updateData(newList)
        })
    
        viewModel?.showLoading?.observe(this, Observer { showLoading ->
            pb.visibility = if (showLoading) View.VISIBLE else View.GONE
        })
    
        viewModel?.showError?.observe(this, Observer { showError ->
            (showError)
        })
    
        viewModel?.loadNews()
    }
    

    }

    below MainViewModel.kt

    Suppress("UNCHECKED_CAST")
    class MainViewModel(newsRepository: Any?) : ViewModel(), CoroutineScope {
        // Coroutine's background job
         val job = Job()
         val sportNewsInterface: SportNewsInterface? = null
        // Define default thread for Coroutine as Main and add job
        override val coroutineContext: CoroutineContext = Dispatchers.Main + job
    
         val showLoading = MutableLiveData<Boolean>()
         val sportList = MutableLiveData <List<Article>>()
        val showError = SingleLiveEvent<String>()
    
    
    
        fun loadNews(
    
        ) {
            // Show progressBar during the operation on the MAIN (default) thread
            showLoading.value = true
            // launch the Coroutine
            launch {
                // Switching from MAIN to IO thread for API operation
                // Update our data list with the new one from API
                val result = withContext(Dispatchers.IO) {
                    sportNewsInterface?.getNews()
                }
                // Hide progressBar once the operation is done on the MAIN (default) thread
                showLoading.value = false
                when (result) {
    
                    is UseCaseResult.Success<*> -> {
                        sportList.value = result.data as List<Article>
                    }
                    is Error -> showError.value = result.message
                }
            }
    
    
        }
    
        override fun onCleared() {
            super.onCleared()
            // Clear our job when the linked activity is destroyed to avoid memory leaks
            job.cancel()
        }
    }
    

    below appModules.kt

    const val BASE_URL = "https://newsapi.org/"
    
    val appModules = module {
        // The Retrofit service using our custom HTTP client instance as a singleton
        single {
            createWebService<SportNewsInterface>(
                okHttpClient = createHttpClient(),
                factory = RxJava2CallAdapterFactory.create(),
                baseUrl = BASE_URL
            )
        }
        // Tells Koin how to create an instance of CatRepository
        factory<NewsRepository> { (NewsRepositoryImpl(sportNewsInterface = get())) }
        // Specific viewModel pattern to tell Koin how to build MainViewModel
        viewModel { MainViewModel (newsRepository = get ())  }
    }
    
    /* Returns a custom OkHttpClient instance with interceptor. Used for building Retrofit service */
    fun createHttpClient(): OkHttpClient {
        val client = OkHttpClient.Builder()
        client.readTimeout(5 * 60, TimeUnit.SECONDS)
        return client.addInterceptor {
            val original = it.request()
            val requestBuilder = original.newBuilder()
            requestBuilder.header("Content-Type", "application/json")
            val request = requestBuilder.method(original.method, original.body).build()
            return@addInterceptor it.proceed(request)
        }.build()
    }
    
    /* function to build our Retrofit service */
    inline fun <reified T> createWebService(
        okHttpClient: OkHttpClient,
        factory: CallAdapter.Factory, baseUrl: String
    ): T {
        val retrofit = Retrofit.Builder()
            .baseUrl(baseUrl)
            .addConverterFactory(GsonConverterFactory.create(GsonBuilder().setLenient().create()))
            .addCallAdapterFactory(CoroutineCallAdapterFactory())
            .addCallAdapterFactory(factory)
            .client(okHttpClient)
            .build()
        return retrofit.create(T::class.java)
    }
    

    below NewsRepository.kt where I have implemented NewsRepository

    interface NewsRepository {
        // Suspend is used to await the result from Deferred
        suspend fun getNewsList(): UseCaseResult<Deferred<List<SportNewsResponse>>>
    }
    
    class NewsRepositoryImpl(private val sportNewsInterface: SportNewsInterface) : NewsRepository {
        override suspend fun getNewsList(): UseCaseResult<Deferred<List<SportNewsResponse>>> {
            /*
             We try to return a list of cats from the API
             Await the result from web service and then return it, catching any error from API
             */
            return try {
                val result = sportNewsInterface.getNews()
                UseCaseResult.Success(result) as UseCaseResult<Deferred<List<SportNewsResponse>>>
            } catch (ex: Exception) {
                UseCaseResult.Error(ex)
            }
        }
    }