如何将运行时参数传递给视图模型?
How to pass runtime arguments to a viewmodel?
我有一个如下所示的视图模型:
class FilterByCategoryViewModel @ViewModelInject constructor(
private val dataManager: AppDataManager,
private val networkHelper: NetworkHelper,
private val category: String
) : ViewModel() { ...
}
我将从 ApplicationModule
得到 dataManager
和 networkHelper
。但我需要将 category
作为 运行 时间参数传递。我尝试了以下方法,但出现错误 Could not resolve AssistedModule
.
我也试过如下创建视图模型工厂:
val factory: ViewModelProvider.Factory = object : ViewModelProvider.Factory() {
@NonNull
override fun <T : ViewModel?> create(@NonNull modelClass: Class<T>): T {
return FilterByCategoryViewModel(
category
) as T
}
}
filterByCategoryViewModel = ViewModelProvider(requireActivity(), factory).get(FilterByCategoryViewModel::class.java)
但后来我不得不编辑视图模型以在构造函数中包含 category
参数,并使用字段注入注入 networkHelper
和 dataManager
参数(我不确定是否它是否以这种方式工作)。但它仍然没有用。 Viewmodel 现在看起来如下:
class FilterByCategoryViewModel @ViewModelInject constructor(
private val category: String
) : ViewModel() {
@Inject
lateinit var dataManager: AppDataManager
@Inject
lateinit var networkHelper: NetworkHelper
...
}
现在我在 运行 应用程序时遇到此构建错误:
D:\Workspace\AndroidProjects\RecipeApp\app\build\tmp\kapt3\stubs\debug\com\neeraja\recipeapp\ui\viewmodel\FilterByCategoryViewModel.java:20: error: incompatible types: NonExistentClass cannot be converted to Annotation
@error.NonExistentClass()
^D:\Workspace\AndroidProjects\RecipeApp\app\build\tmp\kapt3\stubs\debug\com\neeraja\recipeapp\ui\viewmodel\FilterByCategoryViewModel.java:34: error: incompatible types: NonExistentClass cannot be converted to Annotation
@error.NonExistentClass()
^
FAILURE: Build completed with 2 failures.
1: Task failed with an exception.
-----------
* What went wrong:
Execution failed for task ':app:checkDebugDuplicateClasses'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.CheckDuplicatesRunnable
> Duplicate class android.support.v4.app.INotificationSideChannel found in modules core-1.3.2-runtime (androidx.core:core:1.3.2) and support-compat-26.1.0-runtime (com.android.support:support-compat:26.1.0)
Duplicate class android.support.v4.app.INotificationSideChannel$Stub found in modules core-1.3.2-runtime (androidx.core:core:1.3.2) and support-compat-26.1.0-runtime (com.android.support:support-compat:26.1.0)
Duplicate class android.support.v4.app.INotificationSideChannel$Stub$Proxy found in modules core-1.3.2-runtime (androidx.core:core:1.3.2) and support-compat-26.1.0-runtime (com.android.support:support-compat:26.1.0)
Duplicate class android.support.v4.os.IResultReceiver found in modules core-1.3.2-runtime (androidx.core:core:1.3.2) and support-compat-26.1.0-runtime (com.android.support:support-compat:26.1.0)
Duplicate class android.support.v4.os.IResultReceiver$Stub found in modules core-1.3.2-runtime (androidx.core:core:1.3.2) and support-compat-26.1.0-runtime (com.android.support:support-compat:26.1.0)
Duplicate class android.support.v4.os.IResultReceiver$Stub$Proxy found in modules core-1.3.2-runtime (androidx.core:core:1.3.2) and support-compat-26.1.0-runtime (com.android.support:support-compat:26.1.0)
Duplicate class android.support.v4.os.ResultReceiver found in modules core-1.3.2-runtime (androidx.core:core:1.3.2) and support-compat-26.1.0-runtime (com.android.support:support-compat:26.1.0)
Duplicate class android.support.v4.os.ResultReceiver found in modules core-1.3.2-runtime (androidx.core:core:1.3.2) and support-compat-26.1.0-runtime (com.android.support:support-compat:26.1.0)
Duplicate class android.support.v4.os.ResultReceiver$MyResultReceiver found in modules core-1.3.2-runtime (androidx.core:core:1.3.2) and support-compat-26.1.0-runtime (com.android.support:support-compat:26.1.0)
Duplicate class android.support.v4.os.ResultReceiver$MyRunnable found in modules core-1.3.2-runtime (androidx.core:core:1.3.2) and support-compat-26.1.0-runtime (com.android.support:support-compat:26.1.0)
Go to the documentation to learn how to <a href="d.android.com/r/tools/classpath-sync-errors">Fix dependency resolution errors</a>.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
==============================================================================
2: Task failed with an exception.
-----------
* What went wrong:
Execution failed for task ':app:kaptDebugKotlin'.
> A failure occurred while executing org.jetbrains.kotlin.gradle.internal.KaptExecution
> java.lang.reflect.InvocationTargetException (no error message)
我正在自学 Hilt、MVVM 和 Kotlin,对此感到非常困惑。对实现这一点有什么建议吗?
我不确定刀柄,但我使用 AssistedInject 对 Dagger2 做了同样的事情。
这是我的实现,
class MyViewModel @AssistedInject constructor(
@Assisted private val savedStateHandle: SavedStateHandle,
dataSource: RemoteDataSource
) : ViewModel() {
@AssistedInject.Factory
interface Factory : AssistedSavedStateViewModelFactory<MyViewModel> {
override fun create(savedStateHandle: SavedStateHandle): MyViewModel
}
val groupId = savedStateHandle.getLiveData("groupId", "")
val searchType = savedStateHandle.getLiveData("searchType", 1)
}
在fragment/activit
val defArgs = bundleOf("groupId" to groupId, "searchType" to searchType)
val factory = viewModelFactory.create(this, defArgs)
viewModel = ViewModelProvider(this, factory)[MyViewModel::class.java]
我终于使用了ViewModelProvider.Factory如下:
class FilterByTypeViewModelFactory constructor(val dataManager: AppDataManager,
val networkHelper: NetworkHelper,
val category: String) : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return FilterByCategoryViewModel(dataManager , networkHelper , category) as T
}
}
ViewModel 现在如下所示:
class FilterByCategoryViewModel @ViewModelInject constructor(
val dataManager: AppDataManager,
val networkHelper: NetworkHelper,
val category: String
) : ViewModel() {
...
}
在片段中:
@AndroidEntryPoint
class FilterByTypeFragment : Fragment() {
@Inject lateinit var dataManager: AppDataManager
@Inject lateinit var networkHelper: NetworkHelper
...
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
if (arguments != null) {
category = arguments?.get("categoryId") as String
val factory = FilterByTypeViewModelFactory(dataManager, networkHelper, category)
filterByCategoryViewModel = ViewModelProvider(requireActivity(), factory).get(FilterByCategoryViewModel::class.java)
}
setupUI()
setupObserver()
}
...
}
这对我有用。我刚刚一直在学习刀柄。我对使用 ViewModelProvider.Factory 或 AssistedInject 等选项感到困惑。虽然这个解决方案对我有用,但我想了解更多关于 AssistedInject 以及我们需要选择其中一个的情况。
我有一个如下所示的视图模型:
class FilterByCategoryViewModel @ViewModelInject constructor(
private val dataManager: AppDataManager,
private val networkHelper: NetworkHelper,
private val category: String
) : ViewModel() { ...
}
我将从 ApplicationModule
得到 dataManager
和 networkHelper
。但我需要将 category
作为 运行 时间参数传递。我尝试了以下方法,但出现错误 Could not resolve AssistedModule
.
我也试过如下创建视图模型工厂:
val factory: ViewModelProvider.Factory = object : ViewModelProvider.Factory() {
@NonNull
override fun <T : ViewModel?> create(@NonNull modelClass: Class<T>): T {
return FilterByCategoryViewModel(
category
) as T
}
}
filterByCategoryViewModel = ViewModelProvider(requireActivity(), factory).get(FilterByCategoryViewModel::class.java)
但后来我不得不编辑视图模型以在构造函数中包含 category
参数,并使用字段注入注入 networkHelper
和 dataManager
参数(我不确定是否它是否以这种方式工作)。但它仍然没有用。 Viewmodel 现在看起来如下:
class FilterByCategoryViewModel @ViewModelInject constructor(
private val category: String
) : ViewModel() {
@Inject
lateinit var dataManager: AppDataManager
@Inject
lateinit var networkHelper: NetworkHelper
...
}
现在我在 运行 应用程序时遇到此构建错误:
D:\Workspace\AndroidProjects\RecipeApp\app\build\tmp\kapt3\stubs\debug\com\neeraja\recipeapp\ui\viewmodel\FilterByCategoryViewModel.java:20: error: incompatible types: NonExistentClass cannot be converted to Annotation
@error.NonExistentClass()
^D:\Workspace\AndroidProjects\RecipeApp\app\build\tmp\kapt3\stubs\debug\com\neeraja\recipeapp\ui\viewmodel\FilterByCategoryViewModel.java:34: error: incompatible types: NonExistentClass cannot be converted to Annotation
@error.NonExistentClass()
^
FAILURE: Build completed with 2 failures.
1: Task failed with an exception.
-----------
* What went wrong:
Execution failed for task ':app:checkDebugDuplicateClasses'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.CheckDuplicatesRunnable
> Duplicate class android.support.v4.app.INotificationSideChannel found in modules core-1.3.2-runtime (androidx.core:core:1.3.2) and support-compat-26.1.0-runtime (com.android.support:support-compat:26.1.0)
Duplicate class android.support.v4.app.INotificationSideChannel$Stub found in modules core-1.3.2-runtime (androidx.core:core:1.3.2) and support-compat-26.1.0-runtime (com.android.support:support-compat:26.1.0)
Duplicate class android.support.v4.app.INotificationSideChannel$Stub$Proxy found in modules core-1.3.2-runtime (androidx.core:core:1.3.2) and support-compat-26.1.0-runtime (com.android.support:support-compat:26.1.0)
Duplicate class android.support.v4.os.IResultReceiver found in modules core-1.3.2-runtime (androidx.core:core:1.3.2) and support-compat-26.1.0-runtime (com.android.support:support-compat:26.1.0)
Duplicate class android.support.v4.os.IResultReceiver$Stub found in modules core-1.3.2-runtime (androidx.core:core:1.3.2) and support-compat-26.1.0-runtime (com.android.support:support-compat:26.1.0)
Duplicate class android.support.v4.os.IResultReceiver$Stub$Proxy found in modules core-1.3.2-runtime (androidx.core:core:1.3.2) and support-compat-26.1.0-runtime (com.android.support:support-compat:26.1.0)
Duplicate class android.support.v4.os.ResultReceiver found in modules core-1.3.2-runtime (androidx.core:core:1.3.2) and support-compat-26.1.0-runtime (com.android.support:support-compat:26.1.0)
Duplicate class android.support.v4.os.ResultReceiver found in modules core-1.3.2-runtime (androidx.core:core:1.3.2) and support-compat-26.1.0-runtime (com.android.support:support-compat:26.1.0)
Duplicate class android.support.v4.os.ResultReceiver$MyResultReceiver found in modules core-1.3.2-runtime (androidx.core:core:1.3.2) and support-compat-26.1.0-runtime (com.android.support:support-compat:26.1.0)
Duplicate class android.support.v4.os.ResultReceiver$MyRunnable found in modules core-1.3.2-runtime (androidx.core:core:1.3.2) and support-compat-26.1.0-runtime (com.android.support:support-compat:26.1.0)
Go to the documentation to learn how to <a href="d.android.com/r/tools/classpath-sync-errors">Fix dependency resolution errors</a>.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
==============================================================================
2: Task failed with an exception.
-----------
* What went wrong:
Execution failed for task ':app:kaptDebugKotlin'.
> A failure occurred while executing org.jetbrains.kotlin.gradle.internal.KaptExecution
> java.lang.reflect.InvocationTargetException (no error message)
我正在自学 Hilt、MVVM 和 Kotlin,对此感到非常困惑。对实现这一点有什么建议吗?
我不确定刀柄,但我使用 AssistedInject 对 Dagger2 做了同样的事情。 这是我的实现,
class MyViewModel @AssistedInject constructor(
@Assisted private val savedStateHandle: SavedStateHandle,
dataSource: RemoteDataSource
) : ViewModel() {
@AssistedInject.Factory
interface Factory : AssistedSavedStateViewModelFactory<MyViewModel> {
override fun create(savedStateHandle: SavedStateHandle): MyViewModel
}
val groupId = savedStateHandle.getLiveData("groupId", "")
val searchType = savedStateHandle.getLiveData("searchType", 1)
}
在fragment/activit
val defArgs = bundleOf("groupId" to groupId, "searchType" to searchType)
val factory = viewModelFactory.create(this, defArgs)
viewModel = ViewModelProvider(this, factory)[MyViewModel::class.java]
我终于使用了ViewModelProvider.Factory如下:
class FilterByTypeViewModelFactory constructor(val dataManager: AppDataManager,
val networkHelper: NetworkHelper,
val category: String) : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return FilterByCategoryViewModel(dataManager , networkHelper , category) as T
}
}
ViewModel 现在如下所示:
class FilterByCategoryViewModel @ViewModelInject constructor(
val dataManager: AppDataManager,
val networkHelper: NetworkHelper,
val category: String
) : ViewModel() {
...
}
在片段中:
@AndroidEntryPoint
class FilterByTypeFragment : Fragment() {
@Inject lateinit var dataManager: AppDataManager
@Inject lateinit var networkHelper: NetworkHelper
...
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
if (arguments != null) {
category = arguments?.get("categoryId") as String
val factory = FilterByTypeViewModelFactory(dataManager, networkHelper, category)
filterByCategoryViewModel = ViewModelProvider(requireActivity(), factory).get(FilterByCategoryViewModel::class.java)
}
setupUI()
setupObserver()
}
...
}
这对我有用。我刚刚一直在学习刀柄。我对使用 ViewModelProvider.Factory 或 AssistedInject 等选项感到困惑。虽然这个解决方案对我有用,但我想了解更多关于 AssistedInject 以及我们需要选择其中一个的情况。