Android Programjaim

Android, Flutter/Dart, Kotlin, Java, Unity, HarmonyOS

Flutter provider architecture

2020. január 08. 16:44 - lacas8282

A provider architecture az amit a Google IO 19 ajanl Flutter ala, igy most ezt is megtanuljuk egyszeruen.
A Google amugy elkezdett egy sajat Provide package gyartasaba, de a Provider annyira jo lett, hogy felkaroltak es a sajatjukat nem is hasznaljak (community edition) Legalabbis a videoban ez hangzik el:D

Rogton a video:


Es akkor egy kis sajat szosszenet.

A Flutter provider package-rol lesz szo: https://pub.dev/packages/provider

Mi a franc ez?:D Egy otvozet a dependency injection es az allapotkezeles kozott, widgetektol widgeteknek!

Kezdjunk is kodolasnak!

Berdobjuk pubspec.yaml-be a:

provider: ^4.0.1


-t majd get

main.dart-ba ez lesz:


import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_provider_sample/counter.dart';
import 'package:flutter_provider_sample/counter_page.dart';
import 'package:provider/provider.dart';


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

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => Counter()),
],
child: Consumer<Counter>(
builder: (context, counter, _) {
return MaterialApp(
home: const CounterPage(),
);
},
),
);
}
}


A szokasos kis counter appunkon mutatjuk be hogyan csinaljak ezt a providernel a nagyok. MyApp root widgetunk van, szokasos... Az elso widget egy Multiprovider widget (ellato/biztosito) lesz, amiben felsorolhatjuk milyen providereket hasznalunk es melyik class-al (celszeru rogton multival kezdeni nagy appoknal). Itt most csak egy Counter osztalyt, amit majd kesobb definialunk a counter.dart file-ban.

ChangeNotifierProvider: egy widget, ami biztosit egy peldanyt a ChangeNotifier osztalybol a leszarmazottainak. Mellesleg eleg okos hozza, hogy csak akkor buildelje ujra az osztalyt, ha abszolut szukseges. Plusz automatikus kezeli a dispose-t/destroy-at az osztalynak, ha mar nem kell.

Tobb infora nem terek most ki, olvashato ezen a linken:  https://pub.dev/packages/provider#-readme-tab-

Consumer: (fogyaszto) -ba kerul maga az a resz, amivel mar hasznalni is tudjuk a biztositott peldanyt.

Es akkor jojjenek a belso osztalyok (counter.dart):

import 'package:flutter/widgets.dart';

class Counter with ChangeNotifier {
int _count = 0;

int get count => _count;

void increment() {
_count++;
notifyListeners();
}

void decrement()
_count--;
notifyListeners();
}
}


A Counter ugye a ChangeNotifierProvider build-jeben kerul be a kepbe, ezert a with keyworddel meghivjuk ra a ChangeNotifier -t. (with-rol olvashatsz a neten meg a mixin keyword-ekrol)

Az osztaly ugy gondolom egyertelmu. van egy _count valtozoja, ami privat es egy getter-e, amivel lekerjuk.
Van dec/inc method-ja. Ami utana hivasra kerul az az erdekesebb: notifyListeners();

Ez rogton erdekes lehet azoknak, akik nativ androidoztak mar, a listanal kell ott hasonlokeppen meghivni, ha tortent valtozas. Ez siman egy listener/observer pattern, ami kb egy event, ami kozli, hogy valtozas tortent.

Observer/listenerbe most nem mennek bele melyebben, eleg ennyit tudni most errol.

counter_page.dart:

class CounterPage extends StatelessWidget {
const CounterPage({Key key}) : super(key: key);

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: null,
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const CounterLabel(),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const DecrementCounterButton(),
const IncrementCounterButton(),
],
),
],
)),
);
}
}

class DecrementCounterButton extends StatelessWidget {
const DecrementCounterButton({Key key}) : super(key: key);

@override
Widget build(BuildContext context) {
return FloatingActionButton(
onPressed: () => Provider.of<Counter>(context, listen: false).decrement(),
tooltip: 'Decrement',
child: const Icon(Icons.remove),
);
}
}

class IncrementCounterButton extends StatelessWidget {
const IncrementCounterButton({Key key}) : super(key: key);

@override
Widget build(BuildContext context) {
return FloatingActionButton(
onPressed: () => Provider.of<Counter>(context, listen: false).increment(),
tooltip: 'Increment',
child: const Icon(Icons.add),
);
}
}

class CounterLabel extends StatelessWidget {
const CounterLabel({Key key}) : super(key: key);

@override
Widget build(BuildContext context) {
final counter = Provider.of<Counter>(context);
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('You have pushed the button this many times:'),
Text('${counter.count}', style: Theme.of(context).textTheme.display1),
],
);
}
}

 

Tehat egy CounterPage osztaly lesz benne, a megjelenito reteg. Mindent kirakott emberunk widget-be kulon osztalyba, es a konstruktorjait const-al ellatta, igyis hivja meg oket.

Miert?

Hat hogy ne kelljen mindig mindent ujrabuildelni, optimalizalas. Viszont a dinamikus tartalom valtozik az observer miatt. Vagyis csak az a widget fog ujrabuildelodni, ami valtozik.

     onPressed: () => Provider.of<Counter>(context, listen: false).decrement(),

Provider-ben levo Counter osztalyra hivatkozunk es a funklciot meghivjuk (amit akarunk).

    final counter = Provider.of<Counter>(context);

itt pedig siman listenelunk ra. Mivel alapbol a listen = true.

ENNYI.

komment
Címkék: provider flutter
süti beállítások módosítása