flutter

La configuración y puesta a punto para el desarrollo en macOSX de aplicaciones Flutter, puede llevar mas tiempo productivo del deseable. Acá sigue el resumen de los inconvenientes y sus soluciones mínimas.

Índice

Conceptos clave

Key concepts

mixin GotosMixin {
  static const _scrollDelta = 200.0;
  static const _refreshTrigger = -60.0;
  
  ...

  void _handleScroll() {
    ...
  }
}

class _LoginPageState extends State<LoginPage> with GotosMixin {
 ...
}

TL;DR

Generando claves utilizando keytool

¡No instales el JDK completo! Muchas soluciones en Stackoverflow lo sugieren. Sin embargo alcanza con utilizar la herramienta que trae el propio Android Studio en la siguiente ruta:

/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/keytool

Generamos la clave para el ambiente debug:

./keytool -genkey -v -keystore ~/[DESTINO]/key2.jks -keyalg RSA -keysize 2048 -validity 10000 -alias androiddebugkey

MacOS X no viene con un JDK preinstalado por lo tanto el comando /usr/libexec/java_home nos devolverá que la versión de JVM no pudo ser encontrada.

Para obtener la huella digital o firma del certificado SHA-1 lo hacemos con el siguiente comando:

./keytool -keystore ~/key.jks -list -v

Para Facebook deberemos generar el hash de la clave de desarrollo. Y recordar que si nuestra app ya se publicó » también debes agregar el hash de clave de activación.»

/keytool -exportcert -alias androiddebugkey -keystore [KEY_PATH] | openssl sha1 -binary | openssl base64

Conservando el estado en un StatefulWidget

// agregar el SingleTickerProviderStateMixin y sobreescribir el getter wantKeepAlive
class _FavoritesViewState extends State<FavoritesView> with SingleTickerProviderStateMixin {

  @override
  bool get wantKeepAlive => true;
}

Actualizar el estado del Widget padre mediante callback

# En el Widget Hijo : Agregar parámetro de la función
# De ser necesario también hacer que acepte parámetros "dynamic Function(int a)?"

class ChildWidget extends StatefulWidget {
  final Function() notifyParent;
  ChildWidget({Key key, @required this.notifyParent}) : super(key: key);
}

# 2.En el Widget Padre : crear una función para que el hijo haga el callback

refresh() {
  setState(() {});
}

# 3. En el Widget Padre : pasar la función como parámetro para el Widget Hijo.

new ChildWidget( notifyParent: refresh );  

# 4. En el Widget Hijo : llamar la función del padre.

  widget.notifyParent();

Existen otras veces que en Flutter necesitamos actualizar datos globales de la aplicación desde una vista del Navigator y actualizar el widget o la vista que queda debajo tras realizar un pop.

Lo hacemos así:

// En la primera página

Navigator.pushNamed(context, '/page2').then((_) => setState(() {}));

// En la segunda página:

Navigator.pop(context);

Esta solución no es propia sino del usuario CopsOnRoad de StackOverflow. Se puede encontrar la respuesta completa en este enlace.

Cambiar el estado de un Widget inmediatamente después del build

Algunas veces necesitamos actualizar un estado en el build. En esta instancia esto no es posible ya que el widget está en construcción, por lo que tenemos que esperar que Flutter termine el renderizado para poder cambiar un estado.

Lo conseguimos de la siguiente manera:

 @override
  void initState() {
    super.initState();
    _lastOrderData = SharedServices.lastShippingDetails(); // futuro

    WidgetsBinding.instance?.addPostFrameCallback((_){

      _lastOrderData.then((value){
        _dropdownValue = value!.city!; // obtenemos el valor deseado y cambiamos el estado
      });

    });

  }

Sobreescribir el Theme para una parte de la aplicación.

A veces necesitamos sobre-escribir el los estilos de nuestra aplicación declarados, por ejemplo como colorScheme, para algún widget en particular, sin afectar al resto de la app.

Para conseguirlo podemos utilizar el widget Theme de la siguiente manera.

Theme.of(context).copyWith(colorScheme: ColorScheme.light(primary: Colors.black))

En este caso estamos redefiniendo el color primario utilizado por el widget showDialog, exclusivamente en este contexto.

El ejemplo completo es el siguiente:

void _showMultiSelect(BuildContext context) async {
    await showDialog(
      context: context,
      //barrierColor: Colors.white,
      useSafeArea: true,
      builder: (context) {
        return Theme(
          data: Theme.of(context).copyWith(colorScheme: ColorScheme.light(primary: Colors.black)),
          child: MultiSelectDialog(
            backgroundColor: Colors.white.withOpacity(1),
            checkColor: Colors.black,
            cancelText: Text("Cancelar"),
            confirmText: Text("Buscar"),
            searchHint: "Buscar",
            title: Text("Tipos de cervezas"),
            searchable: true,
            items: _animals.map((e) => MultiSelectItem(e, e.name)).toList(),
            initialValue: _selectedBeers,
            onConfirm: (values) {
              setState(() {
                _selectedBeers = values;
              });
              Navigator.of(context).pop();
              
            },
          ),
        );
      },
    );
  }

Mas información al respecto en este enlace de la documentación oficial.

Aceptar las licencias del Android SDK

Encontrar el sdkmanager para aceptar las licencias del Android SDK, necesario para trabajar y compilar flutter, puede ser un dolor de cabeza en Mac OS.
Aquí está su ruta, los problemas comunes y las soluciones.

La ruta.

~/Library/Android/sdk/tools/bin/sdkmanager --licenses

Un posible error a encontrar al ejecutar este comando es:

The operation couldn’t be completed. Unable to locate a Java Runtime.
Please visit http://www.java.com for information on installing Java.
Instalamos las herramientas de lineas de comando

Una vez instaladas las herramientas de lineas de comando, podemos volver con el comando previsto para la aceptación de las licencias.

flutter doctor --android-licenses



user-avatar
Escribió para Trabajo
Nicolás Erramuspe
Product developer @ Mínimo