Nanda Z
Nanda Z

Reputation: 1876

How to instance many parameters for Factory class with Kodein

I'm using Kodein as injecting dependency for my kotlin project. So I have a factory of my ViewModel like below

class ReadViewModelFactory(private val readRepository: ReadRepositoryImpl, private val activity: ReadActivity) : ViewModelProvider.NewInstanceFactory() {

    @Suppress("UNCHECKED_CAST")
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {

        val guid = activity.intent.getIntExtra(Constants.EXTRA_GUID, 0)
        val pubDate = activity.intent.getStringExtra(Constants.EXTRA_DATE)
        val title = activity.intent.getStringExtra(Constants.EXTRA_TITLE)
        val headImage = activity.intent.getStringExtra(Constants.EXTRA_IMAGE_URL)
        val kanal = activity.intent.getStringExtra(Constants.EXTRA_KANAL_READ)
        val intentRead = IntentRead(guid, pubDate, title, headImage, kanal)
        return ReadViewModel(readRepository, intentRead) as T
    }
}

Then, in my Application class, I've created:

class App : MultiDexApplication(), KodeinAware{

    override val kodein = Kodein.lazy {
        import(androidXModule(this@App))

        bind() from singleton { NetworkConnectionInterceptor(instance()) }
        bind() from singleton { ApiService(instance()) }
        bind() from provider { ReadViewModelFactory(instance(),instance())}

    }

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

As you can see, I have two params for my ReadViewModelFactory. But when I run my application crash occurred in ReadActivity. What console log said

java.lang.RuntimeException: Unable to start activity ComponentInfo{id.my.app/id.my.app.ui.read.ReadActivity}: org.kodein.di.Kodein$NotFoundException: No binding found for bind() with ?().? { ? } Registered in this Kodein container:

My ReadActivity looks like below:

class ReadActivity : AppCompatActivity(), KodeinAware{

  override val kodein by kodein()

    private val factory : ReadViewModelFactory by instance()

 .......

}

fullstack trace

08-21 11:23:54.807 27186-27186/id.my.app E/AndroidRuntime: FATAL EXCEPTION: main Process: id.my.app, PID: 27186 java.lang.RuntimeException: Unable to start activity ComponentInfo{id.my.app/id.grid.app.ui.read.ReadActivity}: org.kodein.di.Kodein$NotFoundException: No binding found for bind() with ?().? { ? } Registered in this Kodein container: bind() with provider { ReadViewModelFactory } bind() with singleton { HomeFragmentRepositoryImpl } bind() with provider { HomeFragmentViewModelFactory } bind() with provider { HomeViewModelFactory } bind() with singleton { NetworkConnectionInterceptor } bind() with singleton { HomeRepositoryImpl } bind() with singleton { ReadRepositoryImpl } bind() with singleton { ApiService } module ⁣androidModule { bind(tag = "externalCache") with contexted().provider { File } bind() with contexted().provider { MediaProjectionManager } bind() with contexted().provider { JobScheduler } bind(tag = "files") with contexted().provider { File } bind(tag = "cache") with contexted().provider { File } bind() with contexted().provider { TvInputManager } bind() with contexted().provider { PrintManager } bind(tag = "packageCodePath") with contexted().provider { String } bind() with contexted().provider { AccountManager } bind() with contexted().provider { UiModeManager } bind() with contexted().provider { ApplicationInfo } bind() with contexted().provider { Looper } bind() with contexted().provider { WindowManager } bind() with contexted().provider { UsageStatsManager } bind() with contexted().provider { InputMethodManager } bind() with contexted().provider { MediaRouter } bind() with contexted().provider { ActivityManager } bind() with contexted().provider { RestrictionsManager } bind() with contexted().provider { SensorManager } bind() with contexted().provider { LauncherApps } bind() with contexted().provider { Resources.Theme } bind() with contexted().provider { DropBoxManager } bind() with contexted().provider { AccessibilityManager } bind() with contexted().provider { AssetManager } bind() with contexted().provider { CarrierConfigManager } bind() with contexted().provider { AudioManager } bind() with contexted().provider { MidiManager } bind() with contexted().provider { MediaSessionManager } bind() with contexted().provider { InputManager } bind() with contexted().provider { WallpaperManager } bind() with contexted().provider { PackageManager } bind() with contexted().provider { DownloadManager } bind() with contexted().provider { BatteryManager } bind() with contexted().provider { SharedPreferences } bind

Upvotes: 0

Views: 2777

Answers (1)

Salomon BRYS
Salomon BRYS

Reputation: 9584

Your class ReadViewModelFactory has a ReadActivity constructor parameter, which is not bound in Kodein.

There are 2 ways you can solve this:

1. Use context

Because you are retrieving directly in ReadActivity, the activity is the context, so you can bind with context:

bind() from contexted<ReadActivity>.provider { ReadViewModelFactory(instance(), context)}

Then, in ReadActivity, you can retrieve like this:

private val factory : ReadViewModelFactory by instance()

However, in another class, you'd have to specify the context explicitely:

private val factory : ReadViewModelFactory by on(activity).instance()

2. Use factory

You can pass the activity as a parameter, which has the advantage of having the same retrieval syntax everywhere:

bind() from factory { activity: ReadActivity -> ReadViewModelFactory(instance(), activity)}

Then, in retrieval:

private val factory : ReadViewModelFactory by instance(arg = activity)

Upvotes: 4

Related Questions