我有一个接受模型作为构造函数参数之一的viewmodel
。 MainModel
有context
(我需要它来注册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
作为参数的管理器是个好主意吗?我知道将context
、activity
或views
直接传递给我的viewmodel
是不好的。但是,在我的viewModel
中拥有其他具有context
或activity
(如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。