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



我有一个接受模型作为构造函数参数之一的viewmodelMainModelcontext(我需要它来注册broadcastReceiver(。

class MainViewModel(private val test: MyTestReiverHandler) : ViewModel() {
}
class MyTestReiverHandler(context: Context) {
    init {
        val intentFilter = IntentFIlter()
        intentFiler.addAction("android.net.conn.CONNECTIVITY_CHANGE")
        context.registerReceiver(receiver, intentFiler)
    }
    fun doSomething() {
        // do something....
    }
}

我知道viewmodel's不应该有任何参考context.那么这种方法是否正确呢? 或者应该所有需要context的东西,如位置接收器、广播接收器......应该在view又名activity级别处理吗?然后将结果传递给viewmodel

编辑

我还将添加我PermissionManager的其他示例,该示例具有请求某种权限的活动。我想在我所有的viewmodels使用该管理器,在我的viewmodels中拥有某种activity作为参数的管理器是个好主意吗?我知道将contextactivityviews直接传递给我的viewmodel是不好的。但是,在我的viewModel中拥有其他具有contextactivity(如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
        //
    }
}

您可以从AndroidViewModel(application:Application(而不是ViewModel扩展MainViewModel。 现在你可以像使用你的 MainViewModel 一样,应用程序实例可以用来注册你的 broadcastReceiver

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

活动/片段

val viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)

这是正确而简单的。

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

不是全部。我曾经在一个跟踪用户位置的应用程序上工作。由于该应用程序需要长时间跟踪用户位置,其他操作同时工作。我决定在另一个线程中执行此操作,并让 ViewModel 分别广播结果。存储库还需要上下文来构建房间数据库。ViewModel 将需要上下文来实例化存储库。这就是为什么我们有AndroidViewModel而不是ViewModel。如果你愿意,你可以实现依赖注入来避免这种依赖的东西

即使你的用例并不完全明显,我想如果你的用户触发了某些事件,你需要调用这个类的函数。 鉴于这种情况,我会提出以下建议:

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

这将允许您将此接收器处理程序传递到视图模型的函数中

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

创建绑定时,将 ReceiverHandler 固定并注入它。 生成此布局文件后,<variable ../>的字段名称将用于绑定。

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!!)

如果您需要通过观察视图模型的属性来调用函数,则不需要将其注入到viewModel中,因此我对用户交互的假设。

注意:仅当您要调用此特定类的函数时,才需要布局内<data .. />层次结构中的任何<import ..>.xml。

相关内容

  • 没有找到相关文章

最新更新