Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
January 29, 2022 10:49 pm GMT

Flutter Provider Trleri

Flutter'da bir ok Provider tr vardr bunlardan bazlar:

Provider
ListenableProvider
ChangeNotifierProvider
ValueListenableProvider
StreamProvider
FutureProvider
MultiProvider
ProxyProvider
ChangeNotifierProxyProvider

Bu yazda provider trlerini ve bunlardan hangisinin ne zaman kullanlacan reneceiz.

Bunun iin aadaki yapy kullanacaz.

Image description

"Do something" dmesi, uygulama durumunu deitiren herhangi bir uygulama olayn temsil eder.

"Show something" Metin widget', kullanc arayznn uygulama durumunu grntlemesi gereken herhangi bir blmn temsil eder.

Soldaki yeil dikdrtgen ve sadaki mavi dikdrtgen, widget aacnn iki farkl blmn temsil eder. Bir etkinliin ve gncelledii kullanc arayznn uygulamann herhangi bir blmnde olabileceini vurgulamak iin kullanlmlardr.

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('My App')),        body: Row(          mainAxisAlignment: MainAxisAlignment.center,          children: <Widget>[            Container(              padding: const EdgeInsets.all(20),              color: Colors.green[200],              child: RaisedButton(                child: Text('Do something'),                onPressed: () {},              ),            ),            Container(              padding: const EdgeInsets.all(35),              color: Colors.blue[200],              child: Text('Show something'),            ),          ],        ),      ),    );  }}

Provider paketini pubspec.yaml dosyanza ekleyin:

dependencies:  provider: ^6.0.2

Bunu herhangi bir sayfada kullanmak iin aadaki ekilde import edebilirsiniz.

import 'package:provider/provider.dart';

Provider

Tahmin edebileceiniz gibi, Provider, Provider widget trlerinin en temelidir.
Widget aacnda herhangi bir yere bir deer (genellikle bir data model object) salamak iin kullanabilirsiniz.
Ancak, bu deer deitiinde widget aacn gncellemenize yardmc olmaz.

class MyModel {   String someValue = 'Hello';  void doSomething() {    someValue = 'Goodbye';    print(someValue);  }}
import 'package:flutter/material.dart';import 'package:provider/provider.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget {  @override  Widget build(BuildContext context) {    return Provider<MyModel>( //                                <--- Provider      create: (context) => MyModel(),      child: MaterialApp(        home: Scaffold(          appBar: AppBar(title: "Text('My App')),"          body: Row(            mainAxisAlignment: MainAxisAlignment.center,            children: <Widget>[              Container(                padding: const EdgeInsets.all(20),                color: Colors.green[200],                child: Consumer<MyModel>( //                    <--- Consumer                  builder: (context, myModel, child) {                    return RaisedButton(                      child: Text('Do something'),                      onPressed: (){                        // We have access to the model.                        myModel.doSomething();                      },                    );                  },                )              ),              Container(                padding: const EdgeInsets.all(35),                color: Colors.blue[200],                child: Consumer<MyModel>( //                    <--- Consumer                  builder: (context, myModel, child) {                    return Text(myModel.someValue);                  },                ),              ),            ],          ),        ),      ),    );  }}class MyModel { //                                               <--- MyModel  String someValue = 'Hello';  void doSomething() {    someValue = 'Goodbye';    print(someValue);  }}

Bunu altrdnzda aadaki sonucu alrsnz:

Image description

Kullanc arayz, modelden gelen "Hello" metniyle oluturuldu.

Do something dmesine basmak, model zerinde bir olayn gereklemesine neden olacaktr. Ancak, modelin verileri deitirilmi olsa bile, Provider widget arac salad deerlerdeki deiiklikleri dinlemedii iin kullanc arayz yeniden oluturulamad.

ChangeNotifierProvider

Provider widget bileeninden farkl olarak, ChangeNotifierProvider model nesnesindeki deiiklikleri dinler.
Deiiklik olduunda, Consumer altndaki tm widget'lar yeniden oluturacaktr.

Kodda Provider' ChangeNotifierProvider olarak deitirin.
Model snfnn ChangeNotifier' kullanmas (veya extend etmesi) gerekir. Bu sizin notifyListeners()'a erimenizi salar ve notifyListeners()' her ardnzda ChangeNotifierProvider bilgilendirilecek ve Consumer'lar widget'larn yeniden oluturacaktr.

import 'package:flutter/material.dart';import 'package:provider/provider.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget {  @override  Widget build(BuildContext context) {    return ChangeNotifierProvider<MyModel>( //      <--- ChangeNotifierProvider      create: (context) => MyModel(),      child: MaterialApp(        home: Scaffold(          appBar: AppBar(title: Text('My App')),          body: Row(            mainAxisAlignment: MainAxisAlignment.center,            children: <Widget>[              Container(                  padding: const EdgeInsets.all(20),                  color: Colors.green[200],                  child: Consumer<MyModel>( //                  <--- Consumer                    builder: (context, myModel, child) {                      return RaisedButton(                        child: Text('Do something'),                        onPressed: (){                          myModel.doSomething();                        },                      );                    },                  )              ),              Container(                padding: const EdgeInsets.all(35),                color: Colors.blue[200],                child: Consumer<MyModel>( //                    <--- Consumer                  builder: (context, myModel, child) {                    return Text(myModel.someValue);                  },                ),              ),            ],          ),        ),      ),    );  }}class MyModel with ChangeNotifier { //                          <--- MyModel  String someValue = 'Hello';  void doSomething() {    someValue = 'Goodbye';    print(someValue);    notifyListeners();  }}

imdi Do something dmesine bastnzda, metin Hello dan Goodbye a dnr.

Image description

ou uygulamada model snfnz kendi dosyasnda olacak ve ChangeNotifier' kullanmak iin flutter/foundation.dart dosyasn ie aktarmanz gerekecek. Bunun gerekten hayran deilim nk bu, i mantnzn artk framework'e baml olduu ve framework'n bir ayrnt olduu anlamna gelir.

Consumer widget', notifyListeners() arldnda altndaki tm pencere elerini yeniden oluturur.
Butonun gncellenmesi gerekmez, bu nedenle bir Consumer kullanmak yerine Provider.of'u kullanabilir ve listen parametresini "false" olarak ayarlayabilirsiniz.
Bu ekilde, deiiklik olduunda buton yeniden oluturulmaz.

class MyButton extends StatelessWidget {  @override  Widget build(BuildContext context) {    final myModel = Provider.of<MyModel>(context, listen: false);    return RaisedButton(      child: Text('Do something'),      onPressed: () {        myModel.doSomething();      },    );  }}

FutureProvider

FutureProvider, temel olarak FutureBuilder widget'nn etrafndaki bir sarmalaycdr.
Kullanc arayznde gstermesi iin baz initial datalar veriyorsunuz ve ayrca provide etmek istediiniz deerin bir Future'n salyorsunuz.
FutureProvider, Future'n ne zaman tamamlandn dinler ve ardndan Consumerlar widget'larn yeniden oluturmalar iin bilgilendirir.

Aadaki kodda, kullanc arayzne baz initial datalar vermek iin bo bir model kullandm.
Ayrca 3 saniye sonra yeni bir model dndrme ilevi ekledim.
FutureProvider'n bekledii ey budur.

Temel Provider gibi, FutureProvider da modelin kendisindeki deiiklikleri dinlemez. Aadaki kod 2 saniye sonra Do something butonunu yaparak modeli deitirir. UI zerinde herhangi bir etkisi yoktur.

import 'package:flutter/material.dart';import 'package:provider/provider.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget {  @override  Widget build(BuildContext context) {    return FutureProvider<MyModel>( //                      <--- FutureProvider      initialData: MyModel(someValue: 'default value'),      create: (context) => someAsyncFunctionToGetMyModel(),      child: MaterialApp(        home: Scaffold(          appBar: AppBar(title: Text('My App')),          body: Row(            mainAxisAlignment: MainAxisAlignment.center,            children: <Widget>[              Container(                padding: const EdgeInsets.all(20),                color: Colors.green[200],                child: Consumer<MyModel>( //                    <--- Consumer                  builder: (context, myModel, child) {                    return RaisedButton(                      child: Text('Do something'),                      onPressed: (){                        myModel.doSomething();                      },                    );                  },                )              ),              Container(                padding: const EdgeInsets.all(35),                color: Colors.blue[200],                child: Consumer<MyModel>( //                    <--- Consumer                  builder: (context, myModel, child) {                    return Text(myModel.someValue);                  },                ),              ),            ],          ),        ),      ),    );  }}Future<MyModel> someAsyncFunctionToGetMyModel() async { //  <--- async function  await Future.delayed(Duration(seconds: 3));  return MyModel(someValue: 'new data');}class MyModel { //                                               <--- MyModel  MyModel({this.someValue});  String someValue = 'Hello';  Future<void> doSomething() async {    await Future.delayed(Duration(seconds: 2));    someValue = 'Goodbye';    print(someValue);  }}

Image description

FutureProvider, Consumer'a Future<MyModel> tamamlandktan sonra yeniden oluturmasn syler.

Uygulamay balang deerleriyle yeniden oluturmak iin hot restart'a basn.

"Do something" butonuna basmann, Future tamamlandktan sonra bile kullanc arayzn gncellemediini unutmayn.
Bu tr bir ilevsellik istiyorsanz, son blmdeki ChangeNotifierProvider' kullann.

FutureProvider iin kullanm durumunuz, bir dosyadan veya adan baz verileri okumak olabilir.Ancak bunu bir FutureBuilder ile de yapabilirsiniz.Uzman olmayan grme gre, FutureProvider bir FutureBuilder'dan ok daha kullanl deil.Bir salaycya ihtiyacm olursa, muhtemelen bir ChangeNotifierProvider kullanrdm ve bir salaycya ihtiyacm yoksa, muhtemelen bir FutureBuilder kullanrdm.
Yine de bir yorum eklemek isterseniz bunu gncellemekten memnuniyet duyarm.

StreamProvider

StreamProvider, temel olarak StreamBuilder'n etrafndaki bir sarcdr. Bir ak salarsnz ve ardndan akta bir olay olduunda Consumer'lar yeniden oluturulur. Kurulum, yukardaki FutureProvider'a ok benzer.

StreamProvider modelin kendisindeki deiiklikleri dinlemez.
Yalnzca aktaki yeni eventleri dinler.

import 'package:flutter/material.dart';import 'package:provider/provider.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget {  @override  Widget build(BuildContext context) {    return StreamProvider<MyModel>( //                       <--- StreamProvider      initialData: MyModel(someValue: 'default value'),      create: (context) => getStreamOfMyModel(),      child: MaterialApp(        home: Scaffold(          appBar: AppBar(title: Text('My App')),          body: Row(            mainAxisAlignment: MainAxisAlignment.center,            children: <Widget>[              Container(                padding: const EdgeInsets.all(20),                color: Colors.green[200],                child: Consumer<MyModel>( //                    <--- Consumer                  builder: (context, myModel, child) {                    return RaisedButton(                      child: Text('Do something'),                      onPressed: (){                        myModel.doSomething();                      },                    );                  },                )              ),              Container(                padding: const EdgeInsets.all(35),                color: Colors.blue[200],                child: Consumer<MyModel>( //                    <--- Consumer                  builder: (context, myModel, child) {                    return Text(myModel.someValue);                  },                ),              ),            ],          ),        ),      ),    );  }}Stream<MyModel> getStreamOfMyModel() { //                        <--- Stream  return Stream<MyModel>.periodic(Duration(seconds: 1),          (x) => MyModel(someValue: '$x'))      .take(10);}class MyModel { //                                               <--- MyModel  MyModel({this.someValue});  String someValue = 'Hello';  void doSomething() {    someValue = 'Goodbye';    print(someValue);  }}

Image description

StreamProvider, Consumer'a yeni bir stream eventi (ak olay) olduunda yeniden oluturmasn syler.

Uygulamay balang deerleriyle yeniden oluturmak iin hot restart a basn.

"Do something" dmesine basmann kullanc arayzn gncellemediini unutmayn. Bu tr bir ilevsellik istiyorsanz, sadece ChangeNotifierProvider kullann. Aslnda, model nesnenizde bir ak olabilir ve sadece notifyListeners()' arabilirsiniz.
Bu durumda bir StreamProvider'a hi ihtiyacnz olmaz.

ValueListenableProvider

ValueListenableProvider' immutable state model nesnesi ile kullanabilirsiniz ve deimezliin (immutability) baz avantajlar vardr.

class MyModel {  ValueNotifier<String> someValue = ValueNotifier('Hello');  void doSomething() {    someValue.value = 'Goodbye';  }}

ValueListenableProvider ile iindeki deiiklikleri dinleyebilirsiniz. Ancak, kullanc arayznden model zerinde bir method armak istiyorsanz, modeli de salamanz gerekir.
Bu nedenle, aadaki kodda bir Provider'n, MyModel'deki ValueNotifier' ValueListenableProvider'a veren bir Consumer'a MyModel saladn grebilirsiniz.

import 'package:flutter/material.dart';import 'package:provider/provider.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget {  @override  Widget build(BuildContext context) {    return Provider<MyModel>(//                              <--- Provider      create: (context) => MyModel(),      child: Consumer<MyModel>( //                           <--- MyModel Consumer          builder: (context, myModel, child) {            return ValueListenableProvider<String>.value( // <--- ValueListenableProvider              value: myModel.someValue,              child: MaterialApp(                home: Scaffold(                  appBar: AppBar(title: Text('My App')),                  body: Row(                    mainAxisAlignment: MainAxisAlignment.center,                    children: <Widget>[                      Container(                          padding: const EdgeInsets.all(20),                          color: Colors.green[200],                          child: Consumer<MyModel>( //       <--- Consumer                            builder: (context, myModel, child) {                              return RaisedButton(                                child: Text('Do something'),                                onPressed: (){                                  myModel.doSomething();                                },                              );                            },                          )                      ),                      Container(                        padding: const EdgeInsets.all(35),                        color: Colors.blue[200],                        child: Consumer<String>(//           <--- String Consumer                          builder: (context, myValue, child) {                            return Text(myValue);                          },                        ),                      ),                    ],                  ),                ),              ),            );          }),    );  }}class MyModel { //                                             <--- MyModel  ValueNotifier<String> someValue = ValueNotifier('Hello'); // <--- ValueNotifier  void doSomething() {    someValue.value = 'Goodbye';    print(someValue.value);  }}

Image description

"Do something" butonuna basmak, ValueListenableProvider sayesinde "Hello"nun "Goodbye" olarak deimesini salar.

Widget aacnn en stnde bir Consumer yerine Provider.of<MyModel>(context, listen: false) kullanmak muhtemelen daha iyi olur. Aksi takdirde, her seferinde tm aac yeniden ina ederiz.

Provider<MyModel>, myModel'i hem ValueListenableProvider'a hem de "Do something" dmesinin kapanmasna verir.

ListenableProvider

Bunu yalnzca kendi zel provider'nz oluturmanz gerekiyorsa kullanrsnz.

MultiProvider

imdiye kadar ki rneklerimiz yalnzca bir model nesnesi kulland.
kinci tr bir model nesnesi salamanz gerekiyorsa, providerlar i ie yerletirebilirsiniz (yukardaki ValueListenableProvider rneinde yaptm gibi). Ancak, i ie kullanm danktr. Bunu yapmann daha dzgn bir yolu, bir MultiProvider kullanmaktr.

Aadaki rnekte, iki ChangeNotifierProviders ile salanan iki farkl model vardr.

import 'package:flutter/material.dart';import 'package:provider/provider.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget {  @override  Widget build(BuildContext context) {    return MultiProvider( //                                     <--- MultiProvider      providers: [        ChangeNotifierProvider<MyModel>(create: (context) => MyModel()),        ChangeNotifierProvider<AnotherModel>(create: (context) => AnotherModel()),      ],      child: MaterialApp(        home: Scaffold(          appBar: AppBar(title: Text('My App')),          body: Column(            children: <Widget>[              Row(                mainAxisAlignment: MainAxisAlignment.center,                children: <Widget>[                  Container(                      padding: const EdgeInsets.all(20),                      color: Colors.green[200],                      child: Consumer<MyModel>( //            <--- MyModel Consumer                        builder: (context, myModel, child) {                          return RaisedButton(                            child: Text('Do something'),                            onPressed: (){                              // We have access to the model.                              myModel.doSomething();                            },                          );                        },                      )                  ),                  Container(                    padding: const EdgeInsets.all(35),                    color: Colors.blue[200],                    child: Consumer<MyModel>( //              <--- MyModel Consumer                      builder: (context, myModel, child) {                        return Text(myModel.someValue);                      },                    ),                  ),                ],              ),             // SizedBox(height: 5),              Row(                mainAxisAlignment: MainAxisAlignment.center,                children: <Widget>[                  Container(                      padding: const EdgeInsets.all(20),                      color: Colors.red[200],                      child: Consumer<AnotherModel>( //      <--- AnotherModel Consumer                        builder: (context, myModel, child) {                          return RaisedButton(                            child: Text('Do something'),                            onPressed: (){                              myModel.doSomething();                            },                          );                        },                      )                  ),                  Container(                    padding: const EdgeInsets.all(35),                    color: Colors.yellow[200],                    child: Consumer<AnotherModel>( //        <--- AnotherModel Consumer                      builder: (context, anotherModel, child) {                        return Text('${anotherModel.someValue}');                      },                    ),                  ),                ],              ),            ],          ),        ),      ),    );  }}class MyModel with ChangeNotifier { //                        <--- MyModel  String someValue = 'Hello';  void doSomething() {    someValue = 'Goodbye';    print(someValue);    notifyListeners();  }}class AnotherModel with ChangeNotifier { //                   <--- AnotherModel  int someValue = 0;  void doSomething() {    someValue = 5;    print(someValue);    notifyListeners();  }}

Image description

lk "Do something" dmesine basmak, "Hello"yu "Goodbye" olarak deitirecektir. kinci Do something dmesine basmak 0 5 olarak deitirecektir.

Bununla tek ChangeNotifierProvider arasnda pek bir fark yoktur.
Farkl Consumer'larn doru modeli alma yolu, gsterdikleri tre gredir. Yani, Consumer<MyModel>, MyModel'i alr ve Consumer<AnotherModel>, AnotherModel'i alr.

ProxyProvider

Ya salamak istediiniz iki modeliniz varsa, ancak modellerden biri dierine balysa?
Bu durumda bir ProxyProvider kullanabilirsiniz.
Bir ProxyProvider deeri bir providerdan alr ve baka bir provider'a enjekte edilmesini salar.

Bir ProxyProvider kurma ekliniz ilk bata kafa kartrc olabilir, bu yzden bununla ilgili kk bir aklama eklememe izin verin.

MultiProvider(  providers: [    ChangeNotifierProvider<MyModel>(      create: (context) => MyModel(),    ),    ProxyProvider<MyModel, AnotherModel>(      update: (context, myModel, anotherModel) => AnotherModel(myModel),    ),  ],

Temel ProxyProvider'n iki tr vardr. Birinci tip, ikinci tipin bal olduu eydir. Yani, baka bir Provider tarafndan zaten salanm olan bir modeldir. Gncelleme kapannda ikinci model tipine enjekte edilir. nc parametre (anotherModel) nceki yerleik deeri saklar, ancak bunu burada kullanmyoruz. Sadece myModel'i AnotherModel'in yapcsna iletiyoruz.

import 'package:flutter/material.dart';import 'package:provider/provider.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget {  @override  Widget build(BuildContext context) {    return MultiProvider( //                              <--- MultiProvider      providers: [        ChangeNotifierProvider<MyModel>( //               <--- ChangeNotifierProvider          create: (context) => MyModel(),        ),        ProxyProvider<MyModel, AnotherModel>( //          <--- ProxyProvider          update: (context, myModel, anotherModel) => AnotherModel(myModel),        ),      ],      child: MaterialApp(        home: Scaffold(          appBar: AppBar(title: Text('My App')),          body: Column(            children: <Widget>[              Row(                mainAxisAlignment: MainAxisAlignment.center,                children: <Widget>[                  Container(                      padding: const EdgeInsets.all(20),                      color: Colors.green[200],                      child: Consumer<MyModel>( //          <--- MyModel Consumer                        builder: (context, myModel, child) {                          return RaisedButton(                            child: Text('Do something'),                            onPressed: (){                              myModel.doSomething('Goodbye');                            },                          );                        },                      )                  ),                  Container(                    padding: const EdgeInsets.all(35),                    color: Colors.blue[200],                    child: Consumer<MyModel>( //            <--- MyModel Consumer                      builder: (context, myModel, child) {                        return Text(myModel.someValue);                      },                    ),                  ),                ],              ),              Container(                  padding: const EdgeInsets.all(20),                  color: Colors.red[200],                  child: Consumer<AnotherModel>( //          <--- AnotherModel Consumer                    builder: (context, anotherModel, child) {                      return RaisedButton(                        child: Text('Do something else'),                        onPressed: (){                          anotherModel.doSomethingElse();                        },                      );                    },                  )              ),            ],          ),        ),      ),    );  }}class MyModel with ChangeNotifier { //                       <--- MyModel  String someValue = 'Hello';  void doSomething(String value) {    someValue = value;    print(someValue);    notifyListeners();  }}class AnotherModel { //                                      <--- AnotherModel  MyModel _myModel;  AnotherModel(this._myModel);  void doSomethingElse() {    _myModel.doSomething('See you later');    print('doing something else');  }}

Image description

Metin Hello ile balar.

Do something dmesine bastnzda, MyModel metni Goodbye olarak deitirir. MyModel dinleyicisini (ChangeNotifierProvider) bilgilendirir ve kullanc arayz yeni metinle yeniden oluturulur.

"Do something else" dmesine bastnzda, AnotherModel MyModel'i (ProxyProvider tarafndan enjekte edilmitir) alr ve metnini "See you later" olarak deitirir. MyModel dinleyicilerine deiiklikleri bildirdii iin, kullanc arayz tekrar gncellenir. AnotherModel'in deien kendi verileri olsayd, ProxyProvider deiiklikleri dinlemediinden UI gncellenmezdi. Bunun iin bir ChangeNotifierProxyProvider gerekir.

Provider builder ve value constructors

Bitirmeden nce, Provider' kullanmay renirken kafam kartran bir eyi daha aklamak istiyorum.
Provider widget elerinin ou (tm deilse de) iki tr constructor'a sahiptir. basic constructor, model nesnenizi oluturduunuz bir oluturma ilevi alr. Bunu yukardaki rneklerin ounda yaptk.

Provider<MyModel>(  create: (context) => MyModel(),  child: ...)

MyModel Nesnenin create fonksiyonunda oluturulduunu grebilirsiniz .

Nesneniz zaten oluturulduysa ve yalnzca ona bir referans salamak istiyorsanz, value adl named (adlandrlm) constructor' kullanabilirsiniz:

final myModel = MyModel();...Provider<MyModel>.value(    value: myModel,     child: ...)

Burada MyModel daha nce oluturuldu ve sadece referans olarak iletildi. Adan veri yklemek iin modelde bir yntemi arabilmeniz iin modelinizi initState() ynteminde balatm olsaydnz bunu yapardnz.

resource


Original Link: https://dev.to/gulsenkeskin/flutter-provider-turleri-546h

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To