Limit your functions in Kotlin to a specific scope But Which one ContextReciver Or Extension functions
Mozhdeh Nouri Sarani
Android Developer : Kotlin | Mentor | Technical Knowledge Sharing | Team Player
Context Receivers guarantee that a desired function is only invoked within the specified receiver's scope or context. The function also gives us access to the receiver itself and its public members.
The only thing you need is to annotate your function with context( Your Scope)
context(ViewModel)
context(Context)
context(Fragment)
.
.
.
For instance:
Instead of calling viewmodelScope every time when I wanna emit value I can use this scenario.
context(ViewModel)
fun <T> emitToSharedFlow(sharedFlow: MutableSharedFlow<T>, value: T) {
viewModelScope.launch {
sharedFlow.emit(value)
}
}
Usage:
@HiltViewModel
class PictureViewModel @Inject constructor(
private val repository: PictureRepository
) : ViewModel() {
private var photoDataActions = MutableSharedFlow<PhotoDataActions>()
fun updateDataAction(actions: PhotoDataActions) {
emitToSharedFlow(photoDataActions, actions)
}
}
The only way I can use this function is inside a ViewModel and when we create an instance of ViewModel we can't access this function with dot
领英推荐
For instance:
@Composable
fun PhotoScreen() {
val viewModel: PictureViewModel = hiltViewModel()
viewModel.emitToSharedFlow() // error Unresolved reference: emitToSharedFlow
}
You may be tempted to try solving this problem with an extension function, but there's a key difference that we should consider.
Consider the above example with an extension function:
fun <T> ViewModel.emitToSharedFlow(sharedFlow: MutableSharedFlow<T>, value: T) {
viewModelScope.launch {
sharedFlow.emit(value)
}
}
The usage remains the same as above. However, when we create our ViewModel, we can access the function like this:
@Composable
fun PhotoScreen() {
val viewModel: PictureViewModel = hiltViewModel()
// We are able to access this function
viewModel.emitToSharedFlow()
}
The extension function approach is incorrect. Calling emitToSharedFlow() on the ViewModel instance is not what we want. The function must be accessible only within the ViewModel class, not from outside. and with the extension function, we add this ability to all classes that inherit ViewModel but in this case, it's not necessary we just need it to specific ViewModel but we still want to be in ViewModel Scope.
At the end:
In Context Receiver, The Kotlin Bytecode shows that the Java code for context receiver is similar to an extension function, which is a static function that takes receivers in its input arguments.
Android Engineer ? Google Developer Expert for Android ? Kotlin ? KMP ? Sometimes exploring vulnerabilities in Apps for fun
7 个月Insightful ?? btw “Context receivers” are now “Context Parameters”