如何使用 Hilt 将参数从 Activity 传递到 ViewModel(没有 ViewModel 工厂)

How to pass arguments from Activity to ViewModel using Hilt (without a ViewModel Factory)

在我的 activity 中,我有多个变量从 Intent Extras 启动。截至目前,我正在使用 ViewModelFactory 将这些变量作为参数传递给我的 viewModel。

如何消除对带刀柄的 ViewModelFacotory 的需求

这是我的两个变量 Activity class

class CommentsActivity : AppCompatActivity() {

    private lateinit var viewModel: CommentsViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        val contentId = intent.getStringExtra(CONTENT_ID_FIELD) //nullable strings
        val highlightedCommentId = intent.getStringExtra(HIGHLIGHTED_COMMENT_ID_RF) //nullable strings
        
        val commentsViewModelFactory = CommentsViewModelFactory(
            contentId,
            highlightedCommentId
        )

         viewModel = ViewModelProvider(this, commentsViewModelFactory[CommentsViewModel::class.java]


    }
}

这是我的视图模型

class CommentsViewMode(
    contentId : String?,
    highlightedCo;mmentId : String?,
) : ViewModel() {

    //logic code here 

}

我的应用程序已设置为使用 hilt,但在这种情况下,我如何传递这 2 个变量并完全消除 viewModelFactory

诀窍是只初始化这些变量一次,而 activity 可以创建多次。在我的应用程序中,我使用了一个标志。

查看模型:

class CommentsViewModel : ViewModel() {

    private var initialized = false

    private var contentId : String? = null
    private var highlightedCommentId : String? = null
    
    fun initialize(contentId : String?, highlightedCommentId : String?) {
        if (!initialized) {
            initialized = true
            this.contentId = contentId
            this.highlightedCommentId = highlightedCommentId
        }
    }
    //logic code here 

}

此外,您应该知道 dagger 项目中存在一个针对此功能的未解决问题: https://github.com/google/dagger/issues/2287

欢迎关注进度

如果你想有效地使用刀柄,你可以按照以下步骤操作 在您的视图模型中使用@HiltViewModel

@HiltViewModel
class MyViewModel @inject constructor(private val yrParameter): ViewModel {}

而且您不再需要任何 ViewModelFactory!一切都为您完成!在您的 activity 或片段中,您现在可以直接使用 KTX viewModels()。

private val viewModel: MyViewModel by viewModels()

或者如果你想为片段使用基础 classes 并且 activity 你可以使用此代码来传递 viewModel class

abstract class BaseFragment<V: ViewModel, T: ViewDataBinding>(@LayoutRes val layout: Int, viewModelClass: Class<V>) : Fragment() {
    
      private val mViewModel by lazy {
            ViewModelProvider(this).get(viewModelClass)
        }
    
}