Android 安卓MVVM。传递具有上下文作为依赖项的对象

Android 安卓MVVM。传递具有上下文作为依赖项的对象,android,viewmodel,android-mvvm,Android,Viewmodel,Android Mvvm,我有一个viewmodel,它接受model作为构造函数参数之一MainModel具有context(我需要它来注册broadcastReceiver) 我知道viewmodel的不应该引用上下文。那么这种方法正确吗? 或者所有需要上下文的东西,比如位置接收器、广播接收器。。。是否应在视图aka活动级别处理?然后将结果传递给viewmodel 编辑 我还将添加另一个示例,我有PermissionManager,该示例具有请求某种权限的活动。我想将该管理器用于我所有的视图模型在我的视图模型中使用某

我有一个
viewmodel
,它接受model作为构造函数参数之一
MainModel
具有
context
(我需要它来注册
broadcastReceiver

我知道
viewmodel的
不应该引用
上下文
。那么这种方法正确吗? 或者所有需要
上下文的东西,比如位置接收器、广播接收器。。。是否应在
视图
aka
活动
级别处理?然后将结果传递给
viewmodel

编辑

我还将添加另一个示例,我有
PermissionManager
,该示例具有请求某种权限的活动。我想将该管理器用于我所有的
视图模型
在我的
视图模型
中使用某种具有
活动
作为参数的管理器是否是个好主意?。我知道直接将
上下文
活动
视图
传递到我的
视图模型
是不好的。但是,在我的
视图模型中有其他具有
上下文
活动
(如
PermissionManager
)的对象好吗

class MainViewModel(private val permissionManager: PermissionManager) : ViewModel() {
    fun doSomethingWithLocation() {
        permissionManager.requestLocationPermission({
            // do something if permission granted
        })
    }

    fun doSomethingWithCamera() {
        permissionManager.requestCameraPermission({
            // do something if permission granted
        })
    }
}

class DetailViewModel(private val permissionManager: PermissionManager) : ViewModel() {
    fun doSomethingWithLocation() {
        permissionManager.requestLocationPermission({
            // do something if permission granted
        })
    }

    fun doSomethingWithCamera() {
        permissionManager.requestCameraPermission({
            // do something if permission granted
        })
    }
}

class PermissionManager(activity: Activity) {

    private val activityWeakRef = WeakReference(activity)

    fun requestLocationPermission(onPermissionGranted: ((Boolean) -> Unit)) {
        //
        // Location permission implemetntation
        //
    }

    fun requestStoragePermission(onPermissionGranted: ((Boolean) -> Unit)) {
        //
        // Storage permission implemetntation
        //
    }

    fun requestCameraPermission(onPermissionGranted: ((Boolean) -> Unit)) {
        //
        // Camera permission implemetntation
        //
    }
}

尽管您的用例并不完全明显,但我认为如果您的用户触发了某个事件,您需要调用此类的函数。 鉴于这种情况,我建议如下:

<data>

    <variable
        name="receiverHandler"
        type="your.package.MyTestReiverHandler" />

    <variable
            name="viewModel"
            type="your.package.MainViewModel"/>
</data>

这将允许您将此receiverHandler传递到viewModel的函数中

<View
     android:onClick="@{viewModel.doSomething(receiverHandler)}" />

创建绑定时,实例化ReceiverHandler并注入它。 构建此布局文件后,绑定中将使用
的字段名

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    val binding = DataBindingUtil.inflate<MainFragmentBinding>(inflater, R.layout.fragment_main, container, false)
    binding.viewModel = viewModel
    binding.lifecycleOwner = this
    binding.receiverHandler = MyTestReiverHandler(container?.context?.applicationContext!!)
override fun onCreateView(充气机:布局充气机,容器:ViewGroup?,savedInstanceState:Bundle?):视图?{
val绑定=数据绑定直到充气(充气机,右布局,主容器,假)
binding.viewModel=viewModel
binding.lifecycleOwner=此
binding.receiverHandler=MyTestReiverHandler(容器?.context?.applicationContext!!)
如果需要通过观察viewModel的属性来调用函数,则不需要将其注入viewModel,因此我对用户交互的假设是这样的

注意:如果要调用此特定类的函数,则layout.xml中的
层次结构中的任何
都是必需的


您可以从AndroidViewModel(应用程序:应用程序)而不是ViewModel扩展MainViewModel。 现在,您可以像以前一样使用您的MainViewModel,并且应用程序实例可用于注册您的broadcastReceiver

class MainViewModel(application: Application) : AndroidViewModel(application) {

}
活动/片段中

val viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
这是正确和容易的一个

所有需要上下文的东西,比如位置接收器、广播接收器……都应该在活动级别的视图中处理吗


不是所有的。我曾经在一个跟踪用户位置的应用程序上工作。因为该应用程序需要跟踪用户位置很长一段时间,而其他操作同时工作。我决定在另一个线程中这样做,并让ViewModel分别广播结果。存储库还需要上下文来构建房间数据库。ViewModel将需要上下文来实例化存储库。这就是为什么我们有AndroidViewModel而不是ViewModel的原因。如果您希望实现依赖项注入以避免这种依赖项,谢谢您的回答!因此,如果我使用Dagger,例如,就没有必要使用
AndroidViewModel
,我可以简单地使用
ViewModel
?并传递所有必要的对象(如
PermissionManager
)对于我的
viewmodel
?是的,如果你使用Dagger,你可以简单地使用viewmodel。一个问题!如果你需要检查权限,为什么不直接在活动中执行此操作?如果授予权限,让viewmodel执行。我希望有一个地方拥有我的应用程序的所有必要权限。对我来说,我使用了静态方法。我不确定这是不是最好的做法,但我很满意
val viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)