Skip to main content

Command Palette

Search for a command to run...

Como crear tus propios Paquetes Dart para flutter

Updated
6 min read

Paquetes Dart o Plugins?

Antes de iniciar establezcamos la diferencia de ambos

Paquetes Dart: Son paquetes escritos en Flutter y Dart que son independientes a la plataforma (Android, iOS, MacOS, Linux, Windows y lo que sea que venga después), por lo general este tipo de paquetes se usa para reutilizar al máximo nuestros widgets o segmentos de código, por ejemplo: swipperview, loading_indicator, shimmer, etc.

Plugins: Es un tipo de paquete especial escrito para alguna plataforma específica o más de una, por ejemplo Android (Kotlin/Java), iOS (Swift/Objective-C), comúnmente este tipo de paquetes se escriben para tener acceso físico a los recursos del dispositivo, por ejemplo el paquete camera, geolocator, etc

Una vez establecida la diferencia es necesario aclarar que en este tutorial nos centraremos en el primero (Paquetes Dart)

Justificación

Te ha pasado alguna vez que escribes una app luego otra y otra, y hay funcionalidades que se repiten y se vuelve tedioso iniciar de 0, bueno allí está el poder de los paquetes dart, por supuesto puedes copiar tu código del proyecto viejo y pegarlo en el nuevo, pero esto es muy mala práctica y por el camino te creas nuevos bugs que tomaran tu tiempo resolverlos.

Otra alternativa es buscar algún paquete que se ajuste a tus requerimientos en pub.dev lo cual resolverá tu problema en la mayoría de los casos, pero que pasa si los paquetes que ya existen no se ajustan 100% a tus requerimientos, o te ajustas al paquete o te creas uno tu solito, hoy aprenderemos a hacer eso.

Finalmente pero no menos importante tenemos a la reusabilidad y productividad, cuando creas tus propios paquetes la reusabilidad de tu código viene implícita cosa que se traduce en productividad ya que gastas menos tiempo en construir tus aplicaciones.

Qué aprenderemos?

En este tutorial aprenderemos a crear un paquete para nuestro proyecto, una funcionalidad bastante requerida es el scroll infinito, por lo tanto, trabajaremos en ello de manera que además de aprender a hacer el paquete este te sirva para tus proyectos.

Link al repo: https://github.com/fnoceda/flutter_tuto_packages

Te recomiendo que te descargues el proyecto para revisarlo con tranquilidad, antes, durante o después de este tutorial, está escrito en environment: sdk: '>=3.0.1 <4.0.0' por lo que no deberías tener problemas con el null-safety en ejecutarlo de una.

Aclaraciones:

NO nos centraremos en explicar el código ni en el diseño, ese no es el objetivo de este tutorial.

NO utilizaremos ningún gestor de estados, para gustos hay sabores y cada quien prefiere alguno, para evitar complicar las cosas, evitaremos el uso de gestor de estados y utilizaremos puros setStates, lo se, no es bueno, pero lo mantiene simple para el ejemplo, una vez que hayas aprendido a hacer tus paquetes puedes agregarle el gestor de estados que mejor te parezca y hacer volar los setStates y los StatefulWidget.

Para la creación del proyecto y paquete, utilizaremos línea de comandos para así evitar que si usas uno u otro editor tengas problemas en hacerlo, en mi opinion es más fácil hacerlo de esta manera, a la hora de escribir código si será necesario abrirlo

A darle!

Paso 1: Crear un proyecto nuevo

flutter create project_name

Paso 2: Ingresar a la carpeta del proyecto, crear una carpeta llamada packages e ingresar a ella

cd project_name
mkdir packages
cd packages

Paso 3: crear el paquete

flutter create --template=package my_infinite_scroll

Paso 4: Explorar el paquete y escribir el código

En este punto ya podemos abrir nuestro editor de código favorito y escribir lo que queremos que haga nuestro paquete, debería haberte quedado esta estructura.

Las carpetas marcadas (android, ios, linux, macos, windows) que se encuentran en packages/my_infinite_scroll, puedes borrarlas, no las necesitaras y traen algunos problemas de compatibilidad, creo que es un bug, espero lo resuelvan pronto

Debería quedarte finalmente esta estructura

Paso 5: Escribir el código de nuestro paquete

Dentro de la carpeta lib encontrarás un archivo.dart con el mismo nombre que le has puesto al paquete, en nuestro caso seria my_infinite_scroll.dart este viene con un código por defecto, lo puedes borrar, lo cual te va a tirar error en los test, por lo que esos test los puedes comentar o borrar por ahora (como bonus en el repo encontraras un test aplicado a este tutorial)

Aquí tienes la libertad de escribirlo como quieras, en mi caso en el archivo principal hago todos los imports, y cree una carpeta models y otra widgets, allí pondré el código del infinite scroll.

La carpeta models contiene el modelo CustomListTileModel que utilizaré para que desde el programa principal enviar los datos que va a necesitar el widget

La carpeta widgets contiene MyCustomListView el cual es el archivo que contiene el ListView que se utilizara en el programa principal, allí podrás encontrar los listeners para el scroll infinito y la lógica para llamar a la función callback que será enviada como parámetro desde el programa principal además contiene a CustomListTileItem el cual es el ListTile que se dibujara para cada item del Listview, por supuesto este usa de base a CustomListTileModel

¡Y bien, ya tienes tu package listo!

Paso 6: Usar nuestro Dar Package en la aplicación principal

6.1) Añadimos nuestro package al pubspect.yalm

6.2) Llamamos a nuestro widget que está en el nuevo package desde la View

Por supuesto debemos tener los datos iniciales en la variable listViewData y la función que va a retornar los datos nuevos cuando el usuario llegue al final del scroll, eso lo puedes ver en MyHomePage.

import 'dart:math';

import 'package:flutter/material.dart';
import 'package:my_infinite_scroll/my_infinite_scroll.dart';

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List<CustomListTileModel> listViewData = [];

  Future<List<CustomListTileModel>> getMoreData() async {
    await Future.delayed(const Duration(seconds: 2));
    var intValue = Random().nextInt(10);
    List<CustomListTileModel> newList = List<CustomListTileModel>.generate(
      10,
      (index) => CustomListTileModel(
        id: (index * intValue).toString(),
        title: 'Title ${index + listViewData.length}',
        status: 'Status ${index + listViewData.length}',
        subTitle: 'Subtitle ${index + listViewData.length}',
        image: const Icon(Icons.abc),
      ),
    );
    return newList;
  }

  setInitialData() async {
    List<CustomListTileModel> initialData = await getMoreData();
    setState(() {
      print('listViewData.length => ${listViewData.length}');
      listViewData.addAll(initialData);
      print('listViewData.length => ${listViewData.length}');
    });
  }

  @override
  void initState() {
    super.initState();
    setInitialData();
  }

  @override
  Widget build(BuildContext context) {
    Size size = MediaQuery.of(context).size;
    print('build');
    return Container(
      color: Colors.white,
      child: SafeArea(
        child: Scaffold(
          appBar: AppBar(),
          body: Container(
            width: size.width * 0.9,
            margin: EdgeInsets.symmetric(horizontal: size.width * 0.04),
            child: Column(
              children: [
                const Text('You can put your seach box here if you want'),
                Expanded(
                  child: MyCustomListView(
                    initialData: listViewData,
                    loadMoreData: getMoreData,
                    onItemTap: (String id) {
                      print('detail/$id');
                    },
                  ),
                )
              ],
            ),
          ),
        ),
      ),
    );
  }
}

Ya todo esta listo, puedes darle a ejecutar y depurar

De vuelta te dejo el repo por si te lo has pasado mas arriba

Link al repo: https://github.com/fnoceda/flutter_tuto_packages

PD: Si quieres tener un package totalmente independiente del proyecto principal, en lugar de crear tu proyecto como aplicación lo debes crear con el template package y al importar desde el proyecto principal en el pubspect.yalm debe poner la url de github/gitlab con la referencia a la rama, ese sería el único cambio y luce algo similar a esto:

  my_infinite_scroll:
    git:
      url: https://github.fnoceda83.com/flutter/my_infinite_scroll.git
      ref: dev

Por ahora es todo, nos vemos pronto en un próximo tutorial.