【问题标题】:How to use hilt instead of using factory to init the argument in viewModel如何使用 hilt 而不是使用工厂来初始化 viewModel 中的参数
【发布时间】:2020-09-06 08:00:41
【问题描述】:

现在我使用 viewModelFactory 在片段中初始化 viewModel 的参数。

class MyFragment : Fragment() {
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        val binding = FragmentMyBinding.inflate(inflater)
        binding.lifecycleOwner = this
        val argument = MyFragmentArgs.fromBundle(requireArgument()).myArgument
        val viewModelFactory = MyViewModelFactory(myArgument, application)
        binding.viewModel = ViewModelProvider(
                this, viewModelFactory).get(MyViewModel::class.java)
        return binding.root
    }
}

class MyViewModelFactory(
        private val myArgument: MyArgument,
        private val application: Application) : ViewModelProvider.Factory {
    @Suppress("unchecked_cast")
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(MyViewModel::class.java)) {
            return MyViewModel(myArgument, application) as T
        }
        throw IllegalArgumentException("Unknown ViewModel class")
    }
}

相比hilt依赖注入方式,有没有办法直接将参数传递给viewModel?

【问题讨论】:

  • 是您的依赖项运行时或构建时。如果是这样(构建时间),请参阅@AliSh 答案。否则,您现在必须创建一个 viewModel 工厂。那是因为 Hilt 还不支持@AssistedInject

标签: android dagger-hilt


【解决方案1】:

是的。使用 Hilt,您可以完全抛弃工厂模式。

要注入参数,可以使用@ViewModelInject注解,要在活动中注入viewModel,可以使用androidx.activity包中的by viewModels()方法。

这是一个例子。

ProductsViewModel.kt

import androidx.hilt.lifecycle.ViewModelInject

class ProductsViewModel @ViewModelInject constructor(
    private val foo: Foo
    private val bar: Bar
) : ViewModel() 

ProductsActivity.kt

@AndroidEntryPoint
class ProductsActivity : AppCompatActivity(){
    
    val viewModel: ProductsViewModel by viewModels()
    
}

要查看实际情况,您可以查看this repo

【讨论】:

  • 非常好,可以解释一下在初始化 ProductsViewModel 时如何在 ProductsActivity 中传递参数 foo 和 bar。
  • @ViewModelInject 不再可用。他们应该使用@HiltViewModel intead。
【解决方案2】:

您可以使用Hilt 库来实现。您应该首先通过@HiltViewModel 定义您的视图模型并使用构造函数注入(@Inject 用于您的视图模型的构造函数):

@HiltViewModel
class MainViewModel @Inject constructor(val foo: Foo) : ViewModel()

我的 Foo 类是:

class Foo @Inject constructor(val someDependency: Dependency)

如果您有任何其他类需要注入到您的 ViewModel 中,您可以将其添加到您的 hilt 模块中。

最后,您应该在您的活动/片段中实例化您的 ViewModel:

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    val mainViewModel: MainViewModel by viewModels()
}

请注意,我们只讨论构建时间依赖性。对于 Hilt 的运行时依赖项,您仍然必须坚持使用经典的 ViewModelProvider.Factory,因为它尚不支持 @AssistedInject

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多