如何使用 Kodein 实例化 Factory class 的许多参数
How to instance many parameters for Factory class with Kodein
我正在使用 Kodein
作为我的 kotlin
项目的注入依赖项。所以我有一个像下面这样的 ViewModel 工厂
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
}
}
然后,在我的应用程序 class 中,我创建了:
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()
}
}
如您所见,我的 ReadViewModelFactory
有两个参数。但是当我 运行 我的应用程序崩溃发生在 ReadActivity
。控制台日志说了什么
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:
我的 ReadActivity
如下所示:
class ReadActivity : AppCompatActivity(), KodeinAware{
override val kodein by kodein()
private val factory : ReadViewModelFactory by instance()
.......
}
全栈跟踪
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
你的classReadViewModelFactory
有一个ReadActivity
构造函数参数,在Kodein中没有绑定
有两种方法可以解决这个问题:
1.使用上下文
因为你直接在ReadActivity
中检索,所以activity是上下文,所以你可以绑定上下文:
bind() from contexted<ReadActivity>.provider { ReadViewModelFactory(instance(), context)}
然后,在ReadActivity
中,你可以这样检索:
private val factory : ReadViewModelFactory by instance()
然而,在另一个 class 中,您必须明确指定上下文:
private val factory : ReadViewModelFactory by on(activity).instance()
2。使用工厂
您可以将 activity 作为参数传递,其优点是在任何地方都具有相同的检索语法:
bind() from factory { activity: ReadActivity -> ReadViewModelFactory(instance(), activity)}
然后,在检索中:
private val factory : ReadViewModelFactory by instance(arg = activity)
我正在使用 Kodein
作为我的 kotlin
项目的注入依赖项。所以我有一个像下面这样的 ViewModel 工厂
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
}
}
然后,在我的应用程序 class 中,我创建了:
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()
}
}
如您所见,我的 ReadViewModelFactory
有两个参数。但是当我 运行 我的应用程序崩溃发生在 ReadActivity
。控制台日志说了什么
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:
我的 ReadActivity
如下所示:
class ReadActivity : AppCompatActivity(), KodeinAware{
override val kodein by kodein()
private val factory : ReadViewModelFactory by instance()
.......
}
全栈跟踪
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
你的classReadViewModelFactory
有一个ReadActivity
构造函数参数,在Kodein中没有绑定
有两种方法可以解决这个问题:
1.使用上下文
因为你直接在ReadActivity
中检索,所以activity是上下文,所以你可以绑定上下文:
bind() from contexted<ReadActivity>.provider { ReadViewModelFactory(instance(), context)}
然后,在ReadActivity
中,你可以这样检索:
private val factory : ReadViewModelFactory by instance()
然而,在另一个 class 中,您必须明确指定上下文:
private val factory : ReadViewModelFactory by on(activity).instance()
2。使用工厂
您可以将 activity 作为参数传递,其优点是在任何地方都具有相同的检索语法:
bind() from factory { activity: ReadActivity -> ReadViewModelFactory(instance(), activity)}
然后,在检索中:
private val factory : ReadViewModelFactory by instance(arg = activity)