Limit your functions in Kotlin to a specific scope But Which one ContextReciver Or Extension functions

Limit your functions in Kotlin to a specific scope But Which one ContextReciver Or Extension functions

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.

Yves Kalume

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”

要查看或添加评论,请登录

Mozhdeh Nouri Sarani的更多文章

社区洞察

其他会员也浏览了