带刀柄的android ViewModelFactory

带刀柄的android ViewModelFactory,android,dagger-hilt,Android,Dagger Hilt,我首先尝试安卓ViewModel和HiltDI 我从下面的链接中了解到,要在运行时使用值初始化ViewModel,我应该使用ViewModelFactory 但是如何将Hilt与ViewModelFactory一起使用呢 答案似乎在@Assisted中,但我不知道如何找到答案 如何告诉hilt我喜欢将存储库接口注入ViewModel,同时仍然允许ViewModelFactory在运行时使用参数初始化ViewModel?将您的ScoreViewModelFactory传递到ViewModel的内

我首先尝试安卓
ViewModel
Hilt
DI

我从下面的链接中了解到,要在运行时使用值初始化ViewModel,我应该使用
ViewModelFactory

但是如何将
Hilt
ViewModelFactory
一起使用呢

答案似乎在
@Assisted
中,但我不知道如何找到答案


如何告诉hilt我喜欢将存储库接口注入ViewModel,同时仍然允许ViewModelFactory在运行时使用参数初始化ViewModel?

将您的ScoreViewModelFactory传递到ViewModel的内置ktx扩展中。您还可以通过将SavedStateHandle本身与defaultViewModelProviderFactory一起使用活动/片段参数

/*
Gradle Dependencies
def lifecycle_version = "2.2.0"
def hiltLifeVersion = "1.0.0-alpha01"
def hiltVersion = "2.28.1-alpha"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
implementation "com.google.dagger:hilt-android:$hiltVersion"
implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha01"
implementation "androidx.hilt:hilt-work:$hiltLifeVersion"
implementation "androidx.hilt:hilt-common:1.0.0-alpha01"
kapt "com.google.dagger:hilt-android-compiler:$hiltVersion"
kapt "androidx.hilt:hilt-compiler:$hiltLifeVersion"
*/

import androidx.fragment.app.viewModels

@AndroidEntryPoint
class ExampleFragment : Fragment(R.layout.example_fragment) {

    //internally using defaultViewModelProviderFactory 
    private val viewModel : ExampleViewModel by viewModels()

    //or you own viewmodal factory instance --> scoreViewModelFactory
    private val viewModel : ExampleViewModel by viewModels { scoreViewModelFactory }

}

class ExampleViewModel @ViewModelInject constructor(
    private val repository: ExampleRepository,
    @Assisted override val savedStateHandle: SavedStateHandle
) : ViewModel() {

    //bundle args -> String, Int, Parcelable etc.. 
    private val arg1LiveData: MutableLiveData<String> = 
                         savedStateHandle.getLiveData("arg1", "")

}
/*
梯度依赖
def lifecycle_version=“2.2.0”
def hiltLifeVersion=“1.0.0-alpha01”
def hiltVersion=“2.28.1-alpha”
实现“androidx.lifecycle:lifecycle viewmodel ktx:$lifecycle\u版本”
实现“androidx.lifecycle:lifecycle viewmodel savedstate:$lifecycle_版本”
实现“androidx.lifecycle:lifecycle livedata ktx:$lifecycle\u版本”
实现“com.google.dagger:hiltandroid:$hiltVersion”
实现“androidx.hilt:hilt生命周期视图模型:1.0.0-alpha01”
实现“androidx.hilt:hilt工作:$hiltLifeVersion”
实现“androidx.hilt:hilt common:1.0.0-alpha01”
kapt“com.google.dagger:hilt android编译器:$hilt版本”
kapt“androidx.hilt:hilt编译器:$hiltLifeVersion”
*/
导入androidx.fragment.app.viewModels
@雄蕊识别点
类ExampleFragment:Fragment(R.layout.example\u Fragment){
//在内部使用defaultViewModelProviderFactory
private val viewModel:ExampleViewModel by viewModels()
//或者您拥有viewmodal工厂实例-->scoreViewModelFactory
私有val viewModel:ExampleViewModelByViewModels{scoreViewModelFactory}
}
类ExampleViewModel@ViewModelInject构造函数(
私有val存储库:示例存储库,
@辅助覆盖val savedStateHandle:savedStateHandle
):ViewModel(){
//bundle args->String、Int、Parcelable等。。
private val arg1LiveData:MutableLiveData=
savedStateHandle.getLiveData(“arg1”、“arg1”)
}
Fragment viewmodel的内置ktx扩展

@MainThread
inline fun <reified VM : ViewModel> Fragment.viewModels(
    noinline ownerProducer: () -> ViewModelStoreOwner = { this },
    noinline factoryProducer: (() -> Factory)? = null
) = createViewModelLazy(VM::class, { ownerProducer().viewModelStore }, factoryProducer)
@MainThread
inline fun Fragment.viewModels(
noinline ownerProducer:()->ViewModelStoreOwner={this},
noinline factoryProducer:(()->Factory)?=null
)=createViewModelLazy(VM::class,{ownerProducer().viewModelStore},factoryProducer)

由@Elye提供,接下来的文章帮助很大。我推荐一本书

似乎大部分工厂都不需要,因为大部分
viewmodel
初始参数都取自前面的片段,可以通过
savedstateholder
访问,如果标记为@Assisted,则会自动注入

为了设置hilt,我使用了下面的代码实验室教程

然后,
viewModel
注入只使用下一个代码自动完成

请注意,正如Fabiocolini所指出的那样,
savedStateHandle
似乎也可以通过简单地将参数名称作为键来获取值。事实上,这就是我在下面的例子中所做的。ps:为了使安全参数更“安全”,我尝试用
ItemsFragmentArgs
替换
savedstateholder
,希望它能工作,但应用程序没有编译。我真的希望将来能实施(如果已经实施,请告诉我)

//ItemFragment文件
@雄蕊识别点
类ItemsFragment:Fragment(){
private val viewModel:ItemsViewModel by viewModels()
//如您所愿使用viewModel。无需初始化。
}
//模块文件-如果您有任何存储库,请记住绑定它
//或者提供代码实验室中提到的精确实现
@InstallIn(ApplicationComponent::class)
@模块
抽象类数据库ModuleBinder{
@束缚
抽象趣味双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语双语
}
//ItemsViewModel文件-最后,声明如下并接受您的参数
//从savedStateHandle(对于安全参数,使用变量名作为键)
类ItemsViewModel@ViewModelInject构造函数(私有值glistRepo:GlistRepository,
@辅助私有val savedstatehold:savedstatehold):ViewModel(){
private val glistLiveDate=glistRepo.getGlistLiveData(
savedstatehold.get(“listId”)!!
)
..
}

希望它能帮助任何人,如果有任何错误,请让我知道

这篇文章可能会提供如何处理此问题的清晰共享我的问题是,我在Fragment中使用了viewmodel,而在Fragment中我没有提到@AndroIdentityPoint。我在活动中提到了这一点,但在片段中没有提到。要在视图模型中使用安全参数,您可以实现我在这里展示的内容:
@ViewModelInject
@Assisted
现在不推荐使用。
//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")!!
    )

..
}
@MainThread
inline fun <reified VM : ViewModel> Fragment.viewModels(
    noinline ownerProducer: () -> ViewModelStoreOwner = { this },
    noinline factoryProducer: (() -> Factory)? = null
) = createViewModelLazy(VM::class, { ownerProducer().viewModelStore }, factoryProducer)
//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")!!
    )

..
}