En aquest tema, explorarem dues maneres fonamentals de gestionar l'estat en Flutter: setState i InheritedWidget. Aquests conceptes són crucials per crear aplicacions reactives i eficients.

Què és l'Estat en Flutter?

L'estat és qualsevol dada que pot canviar durant el cicle de vida d'un widget. Per exemple, el text d'un camp de text, la posició d'un botó o la selecció d'un element en una llista.

setState

setState és una manera senzilla i directa de gestionar l'estat en Flutter. S'utilitza principalment en widgets stateful (StatefulWidget). Quan es crida a setState, Flutter sap que ha de reconstruir el widget amb el nou estat.

Exemple de setState

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Exemple de setState')),
        body: Center(child: CounterWidget()),
      ),
    );
  }
}

class CounterWidget extends StatefulWidget {
  @override
  _CounterWidgetState createState() => _CounterWidgetState();
}

class _CounterWidgetState extends State<CounterWidget> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Text('Has premut el botó aquesta quantitat de vegades:'),
        Text(
          '$_counter',
          style: Theme.of(context).textTheme.headline4,
        ),
        ElevatedButton(
          onPressed: _incrementCounter,
          child: Text('Incrementa'),
        ),
      ],
    );
  }
}

Explicació del Codi

  1. Creació del StatefulWidget: CounterWidget és un widget amb estat.
  2. Definició de l'Estat: _CounterWidgetState és la classe que manté l'estat del widget.
  3. Inicialització de l'Estat: _counter és la variable d'estat que es modifica.
  4. Actualització de l'Estat: _incrementCounter crida a setState per actualitzar _counter i redibuixar el widget.

InheritedWidget

InheritedWidget és una manera més avançada de gestionar l'estat, especialment quan l'estat ha de ser compartit entre múltiples widgets. Permet que els widgets descendents accedeixin a l'estat sense necessitat de passar-lo explícitament a través del constructor.

Exemple de InheritedWidget

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Exemple de InheritedWidget')),
        body: CounterProvider(
          child: CounterWidget(),
        ),
      ),
    );
  }
}

class CounterProvider extends InheritedWidget {
  final int counter;
  final Function() incrementCounter;

  CounterProvider({Key? key, required Widget child})
      : counter = 0,
        incrementCounter = () {},
        super(key: key, child: child);

  @override
  bool updateShouldNotify(CounterProvider oldWidget) {
    return oldWidget.counter != counter;
  }

  static CounterProvider? of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<CounterProvider>();
  }
}

class CounterWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final provider = CounterProvider.of(context);

    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Text('Has premut el botó aquesta quantitat de vegades:'),
        Text(
          '${provider?.counter}',
          style: Theme.of(context).textTheme.headline4,
        ),
        ElevatedButton(
          onPressed: provider?.incrementCounter,
          child: Text('Incrementa'),
        ),
      ],
    );
  }
}

Explicació del Codi

  1. Creació del InheritedWidget: CounterProvider és un InheritedWidget que conté l'estat i una funció per incrementar-lo.
  2. Mètode of: Permet als widgets descendents accedir a l'estat del CounterProvider.
  3. Ús del InheritedWidget: CounterWidget accedeix a l'estat a través del mètode of.

Comparació entre setState i InheritedWidget

Característica setState InheritedWidget
Facilitat d'ús Fàcil Més complex
Escalabilitat Limitada a widgets individuals Ideal per a compartir estat
Rendiment Pot ser menys eficient en grans apps Més eficient per a estat compartit
Casos d'ús Estat local Estat global o compartit

Exercici Pràctic

Exercici

Crea una aplicació Flutter que utilitzi InheritedWidget per gestionar l'estat d'un comptador que es pot incrementar des de diferents pantalles.

Solució

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: CounterProvider(
        child: HomeScreen(),
      ),
    );
  }
}

class CounterProvider extends StatefulWidget {
  final Widget child;

  CounterProvider({required this.child});

  @override
  _CounterProviderState createState() => _CounterProviderState();

  static _CounterProviderState? of(BuildContext context) {
    return context.findAncestorStateOfType<_CounterProviderState>();
  }
}

class _CounterProviderState extends State<CounterProvider> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return _InheritedCounter(
      counter: _counter,
      incrementCounter: _incrementCounter,
      child: widget.child,
    );
  }
}

class _InheritedCounter extends InheritedWidget {
  final int counter;
  final Function() incrementCounter;

  _InheritedCounter({
    required this.counter,
    required this.incrementCounter,
    required Widget child,
  }) : super(child: child);

  @override
  bool updateShouldNotify(_InheritedCounter oldWidget) {
    return oldWidget.counter != counter;
  }
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final provider = CounterProvider.of(context);

    return Scaffold(
      appBar: AppBar(title: Text('Home Screen')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('Has premut el botó aquesta quantitat de vegades:'),
            Text(
              '${provider?._counter}',
              style: Theme.of(context).textTheme.headline4,
            ),
            ElevatedButton(
              onPressed: provider?._incrementCounter,
              child: Text('Incrementa'),
            ),
            ElevatedButton(
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => SecondScreen()),
                );
              },
              child: Text('Anar a la Segona Pantalla'),
            ),
          ],
        ),
      ),
    );
  }
}

class SecondScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final provider = CounterProvider.of(context);

    return Scaffold(
      appBar: AppBar(title: Text('Second Screen')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('Has premut el botó aquesta quantitat de vegades:'),
            Text(
              '${provider?._counter}',
              style: Theme.of(context).textTheme.headline4,
            ),
            ElevatedButton(
              onPressed: provider?._incrementCounter,
              child: Text('Incrementa'),
            ),
          ],
        ),
      ),
    );
  }
}

Explicació de la Solució

  1. CounterProvider: Un StatefulWidget que conté l'estat del comptador i una funció per incrementar-lo.
  2. _InheritedCounter: Un InheritedWidget que proporciona l'estat i la funció d'increment a tots els widgets descendents.
  3. HomeScreen i SecondScreen: Dues pantalles que accedeixen i modifiquen l'estat del comptador a través del CounterProvider.

Conclusió

En aquest tema, hem après a gestionar l'estat en Flutter utilitzant setState i InheritedWidget. Hem vist exemples pràctics de com utilitzar cada mètode i hem comparat les seves característiques. Amb aquests coneixements, estàs preparat per gestionar l'estat de manera eficient en les teves aplicacions Flutter.

Curs de Desenvolupament Flutter

Mòdul 1: Introducció a Flutter

Mòdul 2: Conceptes Bàsics de Programació en Dart

Mòdul 3: Widgets de Flutter

Mòdul 4: Gestió de l'Estat

Mòdul 5: Navegació i Enrutament

Mòdul 6: Xarxes i APIs

Mòdul 7: Persistència i Emmagatzematge

Mòdul 8: Conceptes Avançats de Flutter

Mòdul 9: Proves i Depuració

Mòdul 10: Desplegament i Manteniment

Mòdul 11: Flutter per a Web i Escriptori

© Copyright 2024. Tots els drets reservats