Desarrollando un sistema, que consta de dos apps según el rol del usuario, ( conductor y pasajero, vendedor y comprador, administrador y empleado, etc ), percate que si bien ya puedo desplegar en ambas plataformas, hay partes de la interfaz y la API que se repite, solo la lógica parece única, entonces surge la necesidad de compartir este código común.
La primera solución fue copiar el código en un paquete dentro de lib, pero como esta en desarrollo se repetirá muchas veces ese paso lo cual suena doloroso, así que probare el concepto de cómo compartirlo entre ambas apps.
bueno, al código.
Creamos 3 aplicaciones: Cliente1, Cliente2 y Librería
$ flutter create --org=com.example.cliente1 Cliente1 $ flutter create --org=com.example.cliente2 Cliente2 $ flutter create --org=com.example.libreria Libreria
Trabajaré en la aplicación Cliente1 agregando la librería y luego repetiré lo mismo en la Cliente2 para comprobarlo.
Lo que necesito probar en este caso es :
– Si se puede compartir widgets
– Si la librería tiene dependencias, estas deben cargarse en la principal o se puede obviar.
– Si se puede configurar variables en la librería desde el cliente.
Tomando el caso del sistema, una parte común entre ambas apps, es el chat.
Primero trabajaremos en la librería
Contenido
Librería
Para probar cada requerimiento se hará:
– Si se puede compartir widgets.
Se implementará un widget del botón que iniciara el chat que cada cliente colocara donde lo necesite.
– Si la librería tiene dependencias, estas deben cargarse en la principal o se puede obviar.
Se usará un paquete de iconos en la librería.
– Si se puede configurar variables en la librería desde el cliente
Se seteará un parámetro que es global en la librería, para ver como se comporta en el cliente..
Primero implementé como si fuera un proyecto normal para verificar su funcionamiento, separando los componentes que serán reusables.
Repositorio:
https://github.com/JavierSolis/Flutter_DemoLibreria_Libreria
Los cambios para hacerlo librería son:
- Crear un archivo “lib_chat.dart” donde indican que archivos serán expuestos para los clientes. ( nota: aún no tengo ni he visto un convención para los nombres, por el momento le colocare el prefijo de lib_*)
- Al momento de usarlo en cliente, no se puede usar las dependencias que se uso en la librería, pero si se exponen, por ejemplo “flutter_icons.dart”, se pueden usar en el cliente.
- Se creo un nuevo widget “widget_button_chat.dart”, solo para encerrar en una clase el botón del chat y usarlo en el cliente.
library lib_chat; //expone el wiget button export 'widget/widget_button_chat.dart'; //expone la página del chat export 'page/chat_page.dart'; //expone la configuración que usa el chat export 'constants.dart'; //agregado después para exponer la dependencia que se uso en la librería export 'package:flutter_icons/flutter_icons.dart';
import 'package:Libreria_chat/page/chat_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_icons/flutter_icons.dart'; class ButtonChatWidget extends StatelessWidget { final String urlContactPhoto; final String nameContact; const ButtonChatWidget({Key key, this.nameContact, this.urlContactPhoto}) : super(key: key); @override Widget build(BuildContext context) { return FloatingActionButton( onPressed: () { Navigator.pushReplacement( context, MaterialPageRoute( builder: (BuildContext context) => ChatPage( contactName: this.nameContact, urlContactPhoto: this.urlContactPhoto))); }, child: Icon(AntDesign.message1), ); } }
- En pubspec.yaml no es necesario ningún cambio, pero para poder identificarlo mejor, cambie el nombre a “libreria_chat“, eso conllevo cambiar el paquete en algunos archivos.
name: Libreria_chat description: Libreria de chat ...
import 'package:Libreria_chat/constants.dart'; import 'package:Libreria_chat/widget/widget_chat.dart'; import 'package:flutter/material.dart'; class ChatPage extends StatelessWidget {
Repositorio:
https://github.com/JavierSolis/Flutter_DemoLibreria_Libreria_refactorizado
Cliente 1
Para usar la librería en el Cliente 1, se agrega la dependencia en pubspec.yaml. indicando el nombre “Libreria_chat” y la ruta “path:“
... dependencies: flutter: sdk: flutter Libreria_chat: path: ../LibreriaRefactorizado #ruta a la librería # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.0 ...
En main.dart , agregue el botón button_chat_widget y un icono de una dependencia de la librería Icon(AntDesign.message1) ( esto se pudo después de exponerlo en la librería por defecto sus dependencias no están disponibles) y se configuro la variable constante en la librería CHAT_USER_NAME.
import 'package:Libreria_chat/constants.dart'; import 'package:Libreria_chat/widget/widget_button_chat.dart'; import 'package:flutter_icons/flutter_icons.dart'; import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( theme: ThemeData( primarySwatch: Colors.blue, visualDensity: VisualDensity.adaptivePlatformDensity, ), home: MyHomePage(title: 'Cliente 1'), ); } } class MyHomePage extends StatefulWidget { MyHomePage({Key key, this.title}) : super(key: key); final String title; @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { int _counter = 0; void _incrementCounter() { setState(() { _counter++; }); } @override Widget build(BuildContext context) { CHAT_USER_NAME = "Javier Solis"; return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Icon(AntDesign.message1), Text( 'You have pushed the button this many times:', ), Text( '$_counter', style: Theme.of(context).textTheme.headline4, ), ], ), ), floatingActionButton: ButtonChatWidget( urlContactPhoto: "https://crop-circle.imageonline.co/images/picture.png", nameContact: "Raul", )); } }
Video:
Repositorio:
https://github.com/JavierSolis/Flutter_DemoLibreria_Cliente_1
y listo.
Tenemos una librería que podemos rehusar. Ahora podemos tener una librerías de utilitarios que podemos usar en todas nuestras app ( notificaciones, login, control de permisos , etc) que ahorrara tiempo en configurar, en grupo de apps conductor/cliente, etc.
Notas adicionales:
- Si tengo abierto la librería y hago un cambio, luego haces hotreload en el cliente, los cambios en la librería se cargarán.
- No implemente el cliente 2, porque los pasos son los mismos al cliente 1.
- La librería también se puede publicar en pub.dev o referenciar desde github.
Referencias:
Iconos de ejemplo
https://pub.dev/packages/flutter_icons
Lista
https://googleflutter.com/flutter-add-item-to-listview-dynamically/
Border rounded
https://stackoverflow.com/a/57778500