带柄的android ViewModelFactory [英] android ViewModelFactory with hilt
问题描述
我首先尝试使用android ViewModel
和 Hilt
DI
I am first trying android ViewModel
and Hilt
DI
据我从下面的链接了解,要使用运行时值初始化ViewModel,我应该使用 ViewModelFactory
As i understand from below link, to initialize ViewModel with a value on run-time i should use 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
,如下面的链接所述
And to use ViewModel with hilt i should use @ViewModelInject
as explained in below link
//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
一起使用?
But how to use Hilt
with ViewModelFactory
?
答案似乎在 @Assisted
中,但是我不知道怎么做
It seems the answer is in the @Assisted
but i can't figure out how
如何告诉我我喜欢它向ViewModel注入存储库接口,同时仍然允许ViewModelFactory在运行时使用参数初始化ViewModel?
How to tell hilt i like it to inject repository interfaces to ViewModel while still allowing ViewModelFactory to initialize the ViewModel with parameters on run-time?
推荐答案
由@Elye提供,接下来的文章有很大帮助.我建议阅读.
courtesy of @Elye, next articles helped a lot. I recommend a read.
似乎不需要大多数Factory,因为大多数 viewmodel
初始参数取自先前的片段,可以通过 SavedStateHandle
进行访问,如果将其标记为@Assisted,则会自动注入
It seems that mostly Factory is not needed since mostly viewmodel
initial parameters are taken from previous fragment and can be accessed via SavedStateHandle
which is automatically injected if marked as @Assisted
为了进行设置,我使用了以下代码实验室教程
To set-up hilt i used the following code-labs tutorial
然后,仅使用下一个代码自动完成 viewModel
注入
Then, viewModel
injection is done automatically using only the next code
请注意,正如fabioCollini 此处所述,它似乎是 savedStateHandle 通过将参数名称简单地放置为安全参数,代码也可以从安全参数获取值钥匙.实际上,这就是我在以下示例中所做的.ps:为了使安全参数更安全",我确实尝试将
SavedStateHandle
替换为 ItemsFragmentArgs
,希望它能正常工作,但该应用程序无法编译.我希望它会在将来实施(如果已经实现,请告诉我)
Note that as noted by fabioCollini here, it seems savedStateHandle
can also get values from safe args by simply placing argument name as the key. In fact, that is what i did in the following example. ps: In an attempt to make the safe args be more "safe", i did try to replace the SavedStateHandle
with ItemsFragmentArgs
hoping it will work but the app did not compile. I do hope it will be implemented in the future (and if already, please let me know)
//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")!!
)
..
}
希望它对任何人都有帮助,如果有任何错误,请告诉我
Hope it helps anyone and if any mistake, please let me know
这篇关于带柄的android ViewModelFactory的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!