Mobiilikehitys Flutterilla · Oppitunti

Provider-paketin perusteet

Oppikaa käyttämään Provider-pakettia, suosittua Flutter-ratkaisua, sovelluksen yksinkertaiseen ja skaalautuvaan tilanhallintaan.

Oppitunti 2/410 vaihetta

Provider-paketin perusteet on ilmainen Mobiilikehitys Flutterilla-oppitunti CoddyKitissä. Tämä on oppitunti 2/4. Voit lukea tästä oppimispolusta kokonaan mitkä tahansa 3 oppituntia ilmaiseksi — sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä käytännön harjoittelun sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Oppitunti kuuluu Mobiilikehitys Flutterilla-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Mobiilikehitys Flutterilla-kurssilla on yhteensä 4 oppituntia.

Mikä Provider on?

Provider-paketti on suosittu ja yksinkertainen ratkaisu Flutterin tilanhallintaan. Se perustuu Flutterin omaan InheritedWidget-widgetiin, joten se on tehokas ja helposti ymmärrettävä.

Sen avulla voitte jakaa tietoja ja tilaa widget-puussa ilman monimutkaisia callback-funktioita tai prop drilling -tekniikkaa.

Tietojen säilyttäjä: ChangeNotifier

Providerin ytimessä on ChangeNotifier-luokka. Laajennatte tätä luokkaa mille tahansa oliolle, joka sisältää jaettavan tilan.

Kun tila muuttuu, kutsutte notifyListeners()-metodia ilmoittaaksenne kaikille kuunteleville widgeteille, että niiden tulee rakentua uudelleen.

import 'package:flutter/material.dart';

// 1. Extend ChangeNotifier
class MyCounter extends ChangeNotifier {
  int _count = 0; // Private state variable

  // Getter to access the count
  int get count => _count;

  // Method to modify state and notify listeners
  void increment() {
    _count++;
    notifyListeners(); // Important! Triggers UI updates
  }
}

Tilan tekeminen saataville

Voitte tehdä ChangeNotifier-instanssin widgetien saataville käyttämällä ChangeNotifierProvider-widgetiä. Sen avulla ympäröitte osan widget-puusta, yleensä koko sovelluksen.

create-callback-funktio tarjoaa instanssin tilaoliostanne.

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

// Our state class from before
class MyCounter extends ChangeNotifier {
  int _count = 0;
  int get count => _count;
  void increment() {
    _count++;
    notifyListeners();
  }
}

void main() {
  runApp(
    // Wrap the app with ChangeNotifierProvider
    ChangeNotifierProvider(
      create: (context) => MyCounter(), // Create an instance
      child: MyApp(), // The widget tree that can access MyCounter
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Provider Setup')),
        body: Center(
          child: Text(
            'MyCounter is now provided!',
            style: TextStyle(fontSize: 24),
          ),
        ),
      ),
    );
  }
}

Käyttöliittymän uudelleenrakentamisen kuunteleminen

Yleisin tapa saada widget kuuntelemaan tilan muutoksia ja rakentamaan käyttöliittymänsä uudelleen on käyttää context.watch()-metodia. Tämä metodi tekee widgetistä riippuvaisen tarjotusta tilasta.

Kun notifyListeners()-metodia kutsutaan, kaikki watch-metodia käyttävät widgetit rakentuvat uudelleen.

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

class MyCounter extends ChangeNotifier {
  int _count = 0;
  int get count => _count;
  void increment() {
    _count++;
    notifyListeners();
  }
}

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => MyCounter(),
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // 1. Use context.watch<MyCounter>() to get the current state
    //    This widget will rebuild when MyCounter changes.
    final counter = context.watch<MyCounter>();

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Watch for Changes')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(
                'Count: ${counter.count}', // Display the count
                style: TextStyle(fontSize: 32),
              ),
              SizedBox(height: 20),
              // Button to increment (action will be added next)
              ElevatedButton(
                onPressed: () {
                  // How to trigger increment? See next scene!
                },
                child: Text('Increment (Not yet connected)'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Toiminnot ilman uudelleenrakentamista

Joskus tarvitsette pääsyn tilan metodeihin, kuten increment()-metodiin, mutta ette halua widgetin rakentuvan uudelleen. Käyttäkää tällöin context.read()-metodia.

Se tarjoaa kertaluonteisen pääsyn tilaolioon eikä muodosta kuuntelusuhdetta.

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

class MyCounter extends ChangeNotifier {
  int _count = 0;
  int get count => _count;
  void increment() {
    _count++;
    notifyListeners();
  }
}

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => MyCounter(),
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final counter = context.watch<MyCounter>(); // Listen for UI updates

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Read for Actions')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(
                'Count: ${counter.count}',
                style: TextStyle(fontSize: 32),
              ),
              SizedBox(height: 20),
              ElevatedButton(
                onPressed: () {
                  // 1. Use context.read<MyCounter>() to get the instance
                  // 2. Call the increment method
                  context.read<MyCounter>().increment();
                },
                child: Text('Increment Counter'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Vaihtoehto kertaluonteiseen käyttöön

Ennen context.read()-metodia yleinen tapa käyttää tilaa ilman kuuntelemista oli Provider.of(context, listen: false).

Se toimii täsmälleen kuten context.read(), mutta read-metodia suositaan usein sen tiiviyden vuoksi. Molemmat sopivat tapahtumankäsittelijöihin, kuten onPressed-käsittelijään.

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

class MyCounter extends ChangeNotifier {
  int _count = 0;
  int get count => _count;
  void increment() {
    _count++;
    notifyListeners();
  }
}

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => MyCounter(),
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final counter = context.watch<MyCounter>(); // UI listens

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Provider.of(listen: false)')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(
                'Count: ${counter.count}',
                style: TextStyle(fontSize: 32),
              ),
              SizedBox(height: 20),
              ElevatedButton(
                onPressed: () {
                  // Use Provider.of with listen: false for one-time access
                  Provider.of<MyCounter>(context, listen: false).increment();
                },
                child: Text('Increment Counter (using Provider.of)'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Hienojakoiset uudelleenrakennukset Consumer-widgetillä

Consumer-widget on toinen tapa kuunnella tilan muutoksia. Toisin kuin context.watch(), joka rakentaa koko widgetin uudelleen, Consumer rakentaa uudelleen vain suoran lapsensa eli builder-funktion.

Tästä voi olla hyötyä suorituskyvyn kannalta, jos vain pienen osan suuresta widgetistä tarvitsee reagoida tilan muutoksiin.

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

class MyCounter extends ChangeNotifier {
  int _count = 0;
  int get count => _count;
  void increment() {
    _count++;
    notifyListeners();
  }
}

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => MyCounter(),
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Consumer Widget')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(
                'This text does NOT rebuild.',
                style: TextStyle(fontSize: 20, color: Colors.grey),
              ),
              SizedBox(height: 20),
              // Only the Text widget inside Consumer rebuilds
              Consumer<MyCounter>(
                builder: (context, counter, child) {
                  print('Consumer rebuilt!'); // See this in console
                  return Text(
                    'Count: ${counter.count}',
                    style: TextStyle(fontSize: 32, fontWeight: FontWeight.bold),
                  );
                },
              ),
            ],
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            context.read<MyCounter>().increment();
          },
          child: Icon(Icons.add),
        ),
      ),
    );
  }
}

Useiden tilojen tarjoaminen

Jos sovelluksessa on useita toisistaan riippumattomia tilaolioita, sovelluksen ympäröiminen monilla ChangeNotifierProvider-widgeteillä voi käydä sekavaksi. MultiProvider yksinkertaistaa tätä.

Se ottaa vastaan providerien luettelon, mikä tekee widget-puusta selkeämmän ja helpommin hallittavan.

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

class MyCounter extends ChangeNotifier {
  int _count = 0;
  int get count => _count;
  void increment() {
    _count++;
    notifyListeners();
  }
}

class MyThemeSettings extends ChangeNotifier {
  bool _isDark = false;
  bool get isDark => _isDark;
  void toggleTheme() {
    _isDark = !_isDark;
    notifyListeners();
  }
}

void main() {
  runApp(
    MultiProvider( // Use MultiProvider for multiple states
      providers: [
        ChangeNotifierProvider(create: (context) => MyCounter()),
        ChangeNotifierProvider(create: (context) => MyThemeSettings()),
      ],
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // Access both states using watch
    final counter = context.watch<MyCounter>();
    final theme = context.watch<MyThemeSettings>();

    return MaterialApp(
      theme: theme.isDark ? ThemeData.dark() : ThemeData.light(),
      home: Scaffold(
        appBar: AppBar(title: Text('MultiProvider Demo')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text('Count: ${counter.count}', style: TextStyle(fontSize: 28)),
              SizedBox(height: 20),
              Text('Dark Mode: ${theme.isDark ? "On" : "Off"}', style: TextStyle(fontSize: 28)),
              SizedBox(height: 30),
              ElevatedButton(
                onPressed: () => context.read<MyThemeSettings>().toggleTheme(),
                child: Text('Toggle Theme'),
              ),
            ],
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () => context.read<MyCounter>().increment(),
          child: Icon(Icons.add),
        ),
      ),
    );
  }
}

Providerin pikatarkistus

Mikä seuraavista on context.read()-metodin ensisijainen tarkoitus Provider-paketissa?

Providerin perusteiden kertaus

Olette oppineet Provider-paketin perusteet!

  • ChangeNotifier sisältää sovelluksen tilan.
  • ChangeNotifierProvider tekee tilan saataville.
  • context.watch() kuuntelee tilan muutoksia ja rakentaa käyttöliittymän uudelleen.
  • context.read() käyttää tilaa toimintoihin ilman uudelleenrakentamista.
  • Provider.of(listen: false) on vanhempi vaihtoehto read-metodille.
  • Consumer mahdollistaa käyttöliittymän hienojakoiset uudelleenrakennukset.
  • MultiProvider auttaa hallitsemaan useita tilaolioita selkeästi.

Provider on tehokas ja joustava työkalu Flutter-sovellusten tilanhallintaan!

Aloita maksutta

Opi Dart tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
22
Oppitunnit
88

Usein kysytyt kysymykset

Onko oppitunti ”Provider-paketin perusteet” ilmainen?

Kyllä — voit lukea täällä verkossa kokonaan ilmaiseksi mitkä tahansa Mobiilikehitys Flutterilla-oppimispolun 3 oppituntia, myös oppitunnin “Provider-paketin perusteet”. Sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä interaktiiviset harjoitukset sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Mobiilikehitys Flutterilla-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Provider-paketin perusteet”?

Oppikaa käyttämään Provider-pakettia, suosittua Flutter-ratkaisua, sovelluksen yksinkertaiseen ja skaalautuvaan tilanhallintaan. Harjoittelet Mobiilikehitys Flutterilla-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni Mobiilikehitys Flutterilla-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin Mobiilikehitys Flutterilla-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 2/4.

Kuinka kauan ”Provider-paketin perusteet”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä Mobiilikehitys Flutterilla-oppitunnilla?

Kyllä. Jokainen Mobiilikehitys Flutterilla-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. setState ja InheritedWidget
  2. Provider-paketin perusteet
  3. Riverpod tilanhallintaan
  4. BLoC-malli Streameilla
← Takaisin: Mobiilikehitys Flutterilla