Usando una Biblioteca Go en Flutter

Cesar Vega
26 mayo, 2019

. . .

Artículo publicado en Medium

Flutter ha hecho posible el desarrollo de aplicaciones móviles de plataforma cruzada con rendimiento nativo. Hasta que tuvimos Flutter solíamos escribir el código de interfaz de usuario específico de la plataforma de la aplicación móvil usando Java/Kotlin para Android y Objective-C/Swift para iOS. Ahora con Flutter podemos usar el mismo código base para App/UI para múltiples plataformas.

Mientras trabajábamos en varios proyectos de desarrollo de aplicaciones móviles en Arputer Technologies escribimos toneladas de lógica de negocio independiente de la plataforma o código de algoritmo en Go y utilizamos la herramienta Gomobile de Google para crear librerías compiladas de forma nativa en Android/iOS que se llaman desde Java/Kotlin o desde la interfaz de usuario de Objective-C/Swift dependiendo de la plataforma. Este enfoque nos ayudó a escribir (y probar) el código core de la lógica del negocio una vez y a utilizarlo en múltiples plataformas (Android, iOS y… Linux, Mac). Mientras trabajábamos con Flutter queríamos reutilizar la misma base de código/API de Go y nos pareció fácil usar las librerías Android/iOS generadas por Gomobile en Flutter usando el canal de plataforma de Flutter.

En este artículo aprenderemos a integrar el código de la librería Go en Flutter y a usarlo en el escenario de plataformas cruzadas. Intentaremos conseguir lo siguiente:

  1. Una simple aplicación Go que recibe una variable integer de Flutter a través del canal de la plataforma y devuelve un valor incrementado de la misma.
  2. Una simple aplicación que envía un número entero a la API nativa de Go y actualiza su widget de estado. Modificaremos la bien conocida aplicación de contador que se genera a partir de la plantilla cuando se crea la aplicación Flutter.

En este artículo asumiremos que la estación de trabajo de desarrollo es Linuxy que ejecuta cualquiera de las últimas distribuciones de Linux y Android se utiliza para probar la aplicación móvil que se va a desarrollar.


Configuración de la estación de trabajo de desarrollo


  1. Asegúrate de que el compilador Go está instalado. ej.: go 1.12.2 linux/amd64
  2. Asegúrate de que el SDK de Android esté instalado. ej.: Android 9.0 (Pie) - Android SDK Platform 28.
  3. Asegúrate de que Android NDK esté instalado ej.: NDK 19.2.x
  4. El emulador Android se instala para probar la aplicación ej: Google Play Intel x86 Atom System Image.

Configuración del entorno para Go


Primero tenemos que preparar el entorno para el desarrollo de Gomobile. Se recomienda instalar la última versión de Go


Variables de entorno


Actualiza las variables de entorno (tu ruta puede ser diferente, por lo tanto, actualiza en consecuencia).

Ten en cuenta que para que gomobile funcione correctamente, debes tener las variables de entorno establecidas y exportadas.


Instalación de Gomobile



Configuración del entorno para Flutter



Crear nuestra Biblioteca de Go para Flutter


Crea $GOPATH/src/gonative-lib/data-processor.go


Compilar y crear la biblioteca de Android


Los siguientes archivos son generados por el comando Gomobile.

  1. gonativelib.aar: Biblioteca Android para ser usada en la aplicación Flutter.
  2. Gonativelib: clase correspondiente al paquete Go.
  3. DataProcessor: clase correspondiente a la estructura Go, que se utilizará en la app.
  4. gonativelib-sources.jar: fuentes Java como referencia.

Tipos de datos compatibles con Gomobile


En la actualidad, un subconjunto de tipos Go son soportados por Gomobile. Para más información, consulta gobind.

  1. Tipos de enteros y de coma flotante con signo.
  2. Tipos String y booleanos.
  3. Tipos slice de bytes. Tenga en cuenta que los slice de bytes se pasan por referencia y admiten mutaciones.
  4. Cualquier tipo de función cuyos parámetros y resultados hayan soportado tipos. Las funciones deben devolver o bien ningún resultado, un resultado, o bien dos resultados en los que el tipo del segundo sea el tipo de ‘error’ incorporado.
  5. Cualquier tipo de interfaz, todos de los cuales, los métodos exportados, han soportado tipos de función.
  6. Cualquier tipo de estructura, todos cuyos métodos exportados han soportado tipos de función y todos cuyos campos exportados han soportado tipos.

Crear la aplicación Flutter


Crea una aplicación flutter a partir de la plantilla predeterminada.

Cuando ejecutes esta aplicación por defecto desde tu IDE favorito deberías poder ver la conocida aplicación con el widget de estado que contiene el botón flotante. Al hacer clic en el botón flotante, el valor del contador se actualiza y se muestra en la interfaz de usuario.

En la aplicación por defecto, el contador se actualiza en _incrementCounter()

Actualizaremos esta función para llamar a la API de la Biblioteca Go en las siguientes secciones.


Añadir la biblioteca Go (Android) a la aplicación Flutter


Primero, agrega Android gonativelib que hemos creado en el paso anterior, a la aplicación Flutter.

Para añadir la gonativelib de Android que hemos creado en el paso anterior, a la aplicación Flutter, cree la carpeta libs en código Android de la aplicación Flutter y copie el archivo aar de Android gonativelib en esta carpeta.

Ahora actualiza ~/workspace/flutter_gonative_app/android/app/build.gradle con lo siguiente:

En relación congit diff flutter_gonative_app/android/app/build.gradle.

Ahora las clases proporcionadas por gonativelib deberían ser accesibles desde Android.

Actualiza

~/workspace/flutter_gonative_app/android/app/src/main/java/com/example/flutter_gonative_app/MainActivity.java con lo siguiente para acceder a gonativelib.DataProcessor.

En relación congit diff flutter_gonative_app/android/app/src/main/java/com/example/flutter_gonative_app/MainActivity.java.

Reinicia la aplicación de flutter para volver a compilarla con los cambios que hayas realizado.


Añadir el canal de plataforma a la aplicación Flutter


Para llamar la API de gonativelib, necesitamos usar el Canal de Plataforma FLutter.


Añadir MethodChannel en Flutter/Dart


La clase _MyHomePageState de la aplicación Flutter contiene el estado actual de las aplicaciones. Necesitamos crear un MethodChannel a través del cual nos comunicaremos con gonalivelib. El cliente y el host del canal hacen el handshake a través del nombre del canal pasado en el MethodChannel constructor del canal de la plataforma. En nuestro caso, el nombre del canal es example.com/gonative. Esto debería ser único en la aplicación.

En el lado Flutter actualiza la función _incrementCounter() desde ~/workspace/flutter_gonative_app/lib/main.dart

En relación con git diff flutter_gonative_app/lib/main.dart.

Entendamos ahora la magia que sucede en el código anterior.

  1. Una vez establecido el MethodChannel, Flutter puede invocar un método (usando invokeMethod()) especificando un método concreto para llamar vía String identifier (en nuestro caso dataProcessor_increment). El invokeMethod devuelve un Future y puede dar lugar a una excepción (por lo tanto, va envuelto en un bloque try-catch).
  2. Una vez que el Future vuelve, _counter se actualiza en la llamada setState() que a su vez actualiza el Widget automáticamente.
  3. Tenga en cuenta que nuestra gonativelibpuede devolver la excepción que se procesa en el lado de Android/Java y se envía de forma transparente a Flutter/Dart. La misma excepción puede ser tratada en on PlatformException catch (e).

Agrega MethodChannel en Android / Java


Ahora en el lado Java de Android actualizaMainActivity.onCreate at ~/workspace/flutter_gonative_app/android/app/src/main/java/com/example/flutter_gonative_app/MainActivity.java con lo siguiente:

En relación con git diff flutter_gonative_app/android/app/src/main/java/com/example/flutter_gonative_app/MainActivity.java

  • onMethodCall maneja la llamada a un método especifico recibida desde Flutter junto con los argumentos. Se recomienda que el argumento sea un Mapa en Flutter/Dart que pueda ser decodificado en el lado Android/Java como se muestra arriba. Para obtener más información acerca de la comprobación de argumentos observa la documentación detallada del método .

Ahora, reinicie la aplicación y cuando haga clic en el botón flotante, Flutter/Dart llama MethodChannel ainvokeMethod con el estado actual del_counter. Al recibir la llamada a través de MethodChannel, predefinido, Android/Java llama al objeto GoNative correspondiente para obtener la salida y devuelve la misma a Flutter.


Nota final


En este artículo he usado un ejemplo trivial para demostrar cómo usar el platform-channel de Flutter para llamar al api GoNative en el contexto de Android. En el caso de iOS se puede utilizar un enfoque similar.

Lo que aprendimos en este artículo:

  1. Desarrollando la API de la biblioteca Go, la cual puede estar compilada en las plataformas origen cruzadas.
  2. Integración de la biblioteca Go en la aplicación Flutter (contexto Android).
  3. Usar el canal de la plataforma en la aplicación Flutter para llamar a bibliotecas específicas de la plataforma (en nuestro caso, la biblioteca nativa Go).
  4. Enviar argumento(s) a Go API desde Flutter y devolver los resultados (sincrónicos) a Flutter para la actualización de la interfaz de usuario.

El código fuente se puede encontrar en Bitbucket/arputer.

En el próximo artículo de esta serie intentaré demostrar un ejemplo de como usar RxDart y EventChannel para lograr esto.

Manténgase en sintonía.

4

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Comunidades en Español