如何将运行时参数传递给视图模型?

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 得到 dataManagernetworkHelper。但我需要将 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 参数,并使用字段注入注入 networkHelperdataManager 参数(我不确定是否它是否以这种方式工作)。但它仍然没有用。 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,对此感到非常困惑。对实现这一点有什么建议吗?

我不确定刀柄,但我使用 A​​ssistedInject 对 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 以及我们需要选择其中一个的情况。