android - 带刀柄的 android ViewModelFactory
问题描述
我首先尝试 androidViewModel
和Hilt
DI
正如我从下面的链接中了解的那样,要使用运行时值初始化 ViewModel,我应该使用ViewModelFactory
//ViewModel
class ScoreViewModel(finalScore: Int) : ViewModel() {
// The final score
var score = finalScore
init {
Log.i("ScoreViewModel", "Final score is $finalScore")
}
}
//ViewModelFactory
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(ScoreViewModel::class.java)) {
return ScoreViewModel(finalScore) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
//Fragment
viewModelFactory = ScoreViewModelFactory(ScoreFragmentArgs.fromBundle(arguments!!).score)
并且要使用带有刀柄的 ViewModel,我应该@ViewModelInject
按照以下链接中的说明使用
//ViewModel
class ExampleViewModel @ViewModelInject constructor(
private val repository: ExampleRepository,
@Assisted private val savedStateHandle: SavedStateHandle
) : ViewModel() {
...
}
//Activity / Fragment
@AndroidEntryPoint
class ExampleActivity : AppCompatActivity() {
private val exampleViewModel: ExampleViewModel by viewModels()
...
}
但是怎么Hilt
用ViewModelFactory
呢?
似乎答案在@Assisted
但我不知道如何
如何告诉 hilt 我喜欢将存储库接口注入 ViewModel,同时仍然允许 ViewModelFactory 在运行时使用参数初始化 ViewModel?
解决方案
由@Elye 提供,下一篇文章很有帮助。我推荐阅读。
通过注入将 Activity Intent 数据传递给 ViewModel
似乎不需要大多数工厂,因为大多数viewmodel
初始参数都是从以前的片段中获取的,并且可以通过SavedStateHandle
标记为@Assisted 时自动注入来访问
为了设置刀柄,我使用了以下代码实验室教程
然后,viewModel
仅使用下一个代码自动完成注入
请注意,正如 fabioCollini在这里所指出的,它似乎savedStateHandle
也可以通过简单地将参数名称作为键来从安全参数中获取值。事实上,这就是我在以下示例中所做的。ps:为了使安全参数更加“安全”,我确实尝试将其替换为SavedStateHandle
希望ItemsFragmentArgs
它可以工作但应用程序没有编译。我确实希望它会在未来实施(如果已经实施,请告诉我)
//ItemFragment file
@AndroidEntryPoint
class ItemsFragment : Fragment() {
private val viewModel: ItemsViewModel by viewModels()
//use viewModel as you would. No need to initialize.
}
//Module file - if you have any repository, remember to bind it
//or provide the exact implementation as noted in code-labs
@InstallIn(ApplicationComponent::class)
@Module
abstract class DatabaseModuleBinder {
@Binds
abstract fun bindGlistRepository(impl: FirestoreGlistRepository): GlistRepository
}
//ItemsViewModel file - lastly, anotate as follows and take your arguments
//from savedStateHandle (for safe args, use variable name as key)
class ItemsViewModel @ViewModelInject constructor(private val glistRepo: GlistRepository,
@Assisted private val savedStateHandle: SavedStateHandle) : ViewModel() {
private val glistLiveDate = glistRepo.getGlistLiveData(
savedStateHandle.get<String>("listId")!!
)
..
}
希望它可以帮助任何人,如果有任何错误,请告诉我
推荐阅读
- elixir - Elixir / Phoenix:服务器因生产中的 eafnosupport 而失败
- sql-server - 授予对报告架构中的视图的 SELECT 权限,但不对不同架构中的基础对象授予 SELECT 权限
- opencv - 使用 opencv 的 calcHist 和 UMat 计算百分位数
- java - 将模型属性从 jsp 传递到控制器 Spring
- php - Codeigniter 4:使用 move_uploaded_file 上传文件
- database - LevelDB如何处理布隆过滤器中的序列号?
- android - 如何让您的应用在 openWith 中显示或与音轨共享
- c# - 在自定义 TaskScheduler 上调度/启动任务时出现问题,这将在所述调度程序上完成执行
- javascript - 省略 setDescription 会导致崩溃
- gradle - build.gradle 不运行测试“无法编译构建文件”