I have a viewmodel
that accepts model as one of a constructor parameters. MainModel
has context
(I need it for registering 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....
}
}
I know that viewmodel's
shouldn't have any reference to context
. So is this approach is correct?
Or should all the things that require context
like location receiver, broadcast receiver, ... should be handled in view
aka activity
level? and then pass as result to viewmodel
?
EDIT
I will also add other example I have PermissionManager
that has activity to ask some kind of permissions. I want to use that manager for all of my viewmodels
Is it a good idea to have some kind of manager that has activity
as a parameter in my viewmodels
?. I know that it is bad to pass context
, activity
or views
directly to my viewmodel
. But is it good to have other objects that has context
or activity
(like PermissionManager
) in my viewModel
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
//
}
}
you can extend your MainViewModel from AndroidViewModel(application: Application) instead of ViewModel. now you can use your MainViewModel just like befor and application instance can be used to register your broadcastReceiver
class MainViewModel(application: Application) : AndroidViewModel(application) {
}
in activity/fragment
val viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
It's the right and easy one.
should all the things that require context like location receiver, broadcast receiver, ... should be handled in view aka activity level?
Not all of them. I used to work on an application that tracks user location. Since the app needs to track user location for a long period of time with other operations working at the same time. I decided to do it in another thread and let the ViewModel broadcasts the result respectively. Repository also needs context to build Room database. ViewModel will need context to instantiate the repository. That's why we have AndroidViewModel over ViewModel. If you wish you can implement Dependency Injection to avoid this dependency stuff