Aplicación de receptores de contexto de Kotlin | de Yves Kalumé | enero 2023

Imagen de Pixabay: https://www.pexels.com/fr-fr/photo/antenna-parabolique-blanche-33153/A veces queremos usar algo en nuestro código solo hasta cierto punto, sin el cual no podemos usar los receptores de contexto usan para expresar limitaciones. Este artículo tiene como objetivo demostrar uno de los muchos casos de uso y problemas que los receptores de contexto de Kotlin pueden resolver utilizando un caso real. Tomemos un ejemplo de Jetpack Compose. Tenemos modificadores a los que solo se puede acceder dentro de un área determinada, como por ejemplo: En Kotlin, puede definir una declaración de contexto restringido usando un Función de extensión de miembrosinterface BoxScope {fun Modifier.align(alignment: Alignment): Modifier} Solo se puede acceder a este modificador en el contexto de BoxScope. Para lograr esto, Compose Box utiliza BoxScope como destinatario de su contenido y puede implementarse como :objeto interno BoxScopeImpl: BoxScope { override fun Modifier.align(alignment: Alignment): Modifier {/*…*/ } } @Composablefun Cuadro (modificador: Modificador = Modificador, contenido: @Composable BoxScope.() -> Unidad) {val medidaPolicy = RememberBoxMeasurePolicy(contentAlignment, propagateMinConstraints)Layout(contenido = { BoxScopeImpl.content() },measurePolicy = medidaPolicy, modificador = modificador) } El contenido de Box tiene acceso a BoxScope, lo que significa que puede usar este Modifier.align().

Descargo de responsabilidad : En el código anterior, solo estaba tratando de simplificar la implementación del cuadro de redacción, el objetivo no era repetirlo exactamente, sino mostrarle uno de los problemas que resuelven los receptores de contexto.

Nuestro problema se refiere a la forma en que se declara el modificador.interface BoxScope {fun Modifier.align(alignment: Alignment): Modifier}

  • Lo más importante es que un La extensión de miembro no se puede declarar en una clase de terceros. La única forma de escribir otro modificador de BoxScope es escribirlo como miembro de BoxScope (lo que significa que esto es imposible).
  • Limita la capacidad de desacoplar, modularizar y estructurar las API en aplicaciones más grandes. No es necesario declarar los modificadores aquí, ya que podemos crear un archivo que contenga la definición de todos ellos.
  • Otra limitación es que solo un destinatario puede representar un contexto. Limita la composición de diferentes abstracciones, ya que no podemos declarar una función que solo necesita llamarse dentro de dos o más ámbitos concurrentes.
  • Etc

Los receptores de contexto son en realidad experimentales y no están habilitados de forma predeterminada. Para habilitar el uso, tenemos que ir construir.gradle.kts o construir.gradle Archivo de nuestro módulo y agregar -Receptor Xcontext como un compilador libre arg. En el construir.gradle Para un archivo de módulo de Android, se parece a esto: android {…kotlinOptions { jvmTarget = ‘1.8’freeCompilerArgs = [«-Xcontext-receivers»]}…}Volvamos a nuestro ejemplo de Modifier.align() y tratemos de introducir el objeto receptor de contexto BoxScope {}context(BoxScope)fun Modifier.align(alignment: Alignment): Modifier {/*…* /} en su lugar de declarar nuestro modificador como una función de extensión de elemento, lo declaramos como una función de nivel superior y especificamos el alcance en el que debe usarse.

Dado que BoxScope no contiene nada, por lo que no tiene sentido implementarlo, prefiero declararlo directamente como un objeto.

Nuestro cuadro sigue siendo casi el mismo, excepto que llamamos directamente a BoxScope.content()@Composablefun Box(modifier: Modifier = Modifier,content: @Composable BoxScope.() -> Unit) {val MeasurePolicy = RememberBoxMeasurePolicy(contentAlignment, propagateMinConstraints)Layout ( content = { BoxScope.content() },measurePolicy = MeasurePolicy,modifier = modificador)} Con esto podemos, por ejemplo, tener otro alcance que se comporte como BoxScope, no necesitamos duplicar el código, solo haremos este alcance como Si necesitamos pasar el destinatario, incluso podemos tener un modificador para ColumnScopecontext(BoxScope,AnOtherLikeBoxScope)fun Modifier.align(alignment: Alignment): Modifier {/*…*/}context(ColumnScope)fun Modifier.align ( alineación: alineación) : Modificador {/*…*/}Los receptores de contexto cubren diferentes casos de uso. Hay varios artículos que proporcionan requisitos previos con ejemplos básicos para ayudarlo a comprender este concepto y sus casos de uso. Personalmente, me he estado preguntando cuál sería el uso de los receptores de contexto en cualquiera de los códigos que ya he escrito o visto, y este artículo está destinado a ayudar a cualquiera que se encuentre en mi lugar.

Deja una respuesta

Tu dirección de correo electrónico no será publicada.