DEV Community

Cover image for Flutter Provider T├╝rleri ­čĺź ­čîî ÔťĘ
G├╝lsen Keskin
G├╝lsen Keskin

Posted on

Flutter Provider T├╝rleri ­čĺź ­čîî ÔťĘ

Flutter'da bir ├žok Provider t├╝r├╝ vard─▒r bunlardan baz─▒lar─▒:

ÔÇó Provider
ÔÇó ListenableProvider
ÔÇó ChangeNotifierProvider
ÔÇó ValueListenableProvider
ÔÇó StreamProvider
ÔÇó FutureProvider
ÔÇó MultiProvider
ÔÇó ProxyProvider
ÔÇó ChangeNotifierProxyProvider

Bu yaz─▒da provider t├╝rlerini ve bunlardan hangisinin ne zaman kullan─▒laca─č─▒n─▒ ├Â─črenece─čiz.

Bunun i├žin a┼ča─č─▒daki yap─▒y─▒ kullanaca─č─▒z.

Image description

ÔÇó "Do something" d├╝─čmesi, uygulama durumunu de─či┼čtiren herhangi bir uygulama olay─▒n─▒ temsil eder.

ÔÇó "Show something" Metin widget'─▒, kullan─▒c─▒ aray├╝z├╝n├╝n uygulama durumunu g├Âr├╝nt├╝lemesi gereken herhangi bir b├Âl├╝m├╝n├╝ temsil eder.

ÔÇó Soldaki ye┼čil dikd├Ârtgen ve sa─čdaki mavi dikd├Ârtgen, widget a─čac─▒n─▒n iki farkl─▒ b├Âl├╝m├╝n├╝ temsil eder. Bir etkinli─čin ve g├╝ncelledi─či kullan─▒c─▒ aray├╝z├╝n├╝n uygulaman─▒n herhangi bir b├Âl├╝m├╝nde olabilece─čini vurgulamak i├žin kullan─▒lm─▒┼člard─▒r.

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'),
            ),

          ],
        ),
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

Provider paketini pubspec.yaml dosyan─▒za ekleyin:

dependencies:
  provider: ^6.0.2
Enter fullscreen mode Exit fullscreen mode

Bunu herhangi bir sayfada kullanmak i├žin a┼ča─č─▒daki ┼čekilde import edebilirsiniz.

import 'package:provider/provider.dart';

Provider

Tahmin edebilece─činiz gibi, Provider, Provider widget t├╝rlerinin en temelidir.
Widget a─čac─▒nda herhangi bir yere bir de─čer (genellikle bir data model object) sa─člamak i├žin kullanabilirsiniz.
Ancak, bu de─čer de─či┼čti─činde widget a─čac─▒n─▒ g├╝ncellemenize yard─▒mc─▒ olmaz.

class MyModel { 
  String someValue = 'Hello';
  void doSomething() {
    someValue = 'Goodbye';
    print(someValue);
  }
}
Enter fullscreen mode Exit fullscreen mode
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);
  }
}
Enter fullscreen mode Exit fullscreen mode

Bunu ├žal─▒┼čt─▒rd─▒─č─▒n─▒zda a┼ča─č─▒daki sonucu al─▒rs─▒n─▒z:

Image description

Kullan─▒c─▒ aray├╝z├╝, modelden gelen "Hello" metniyle olu┼čturuldu.

ÔÇťDo somethingÔÇŁ d├╝─čmesine basmak, model ├╝zerinde bir olay─▒n ger├žekle┼čmesine neden olacakt─▒r. Ancak, modelin verileri de─či┼čtirilmi┼č olsa bile, Provider widget arac─▒ sa─člad─▒─č─▒ de─čerlerdeki de─či┼čiklikleri dinlemedi─či i├žin kullan─▒c─▒ aray├╝z├╝ yeniden olu┼čturulamad─▒.

ChangeNotifierProvider

Provider widget bile┼čeninden farkl─▒ olarak, ChangeNotifierProvider model nesnesindeki de─či┼čiklikleri dinler.
De─či┼čiklik oldu─čunda, Consumer alt─▒ndaki t├╝m widget'lar─▒ yeniden olu┼čturacakt─▒r.

Kodda Provider'─▒ ChangeNotifierProvider olarak de─či┼čtirin.
Model s─▒n─▒f─▒n─▒n ChangeNotifier'─▒ kullanmas─▒ (veya extend etmesi) gerekir. Bu sizin notifyListeners()'a eri┼čmenizi sa─člar ve notifyListeners()'─▒ her ├ža─č─▒rd─▒─č─▒n─▒zda ChangeNotifierProvider bilgilendirilecek ve Consumer'lar widget'lar─▒n─▒ yeniden olu┼čturacakt─▒r.

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();
  }
}
Enter fullscreen mode Exit fullscreen mode

┼×imdi ÔÇťDo somethingÔÇŁ d├╝─čmesine bast─▒─č─▒n─▒zda, metin ÔÇťHelloÔÇŁ dan ÔÇťGoodbyeÔÇŁ a d├Ân├╝┼č├╝r.

Image description

├ço─ču uygulamada model s─▒n─▒f─▒n─▒z kendi dosyas─▒nda olacak ve ChangeNotifier'─▒ kullanmak i├žin flutter/foundation.dart dosyas─▒n─▒ i├že aktarman─▒z gerekecek. Bunun ger├žekten hayran─▒ de─čilim ├ž├╝nk├╝ bu, i┼č mant─▒─č─▒n─▒z─▒n art─▒k framework'e ba─č─▒ml─▒ oldu─ču ve framework'├╝n bir ayr─▒nt─▒ oldu─ču anlam─▒na gelir.

Consumer widget'─▒, notifyListeners() ├ža─čr─▒ld─▒─č─▒nda alt─▒ndaki t├╝m pencere ├Â─čelerini yeniden olu┼čturur.
Butonun g├╝ncellenmesi gerekmez, bu nedenle bir Consumer kullanmak yerine Provider.of'u kullanabilir ve listen parametresini "false" olarak ayarlayabilirsiniz.
Bu ┼čekilde, de─či┼čiklik oldu─čunda buton yeniden olu┼čturulmaz.

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();
      },
    );
  }
}

Enter fullscreen mode Exit fullscreen mode

FutureProvider

FutureProvider, temel olarak FutureBuilder widget'─▒n─▒n etraf─▒ndaki bir sarmalay─▒c─▒d─▒r.
Kullan─▒c─▒ aray├╝z├╝nde g├Âstermesi i├žin baz─▒ initial datalar─▒ veriyorsunuz ve ayr─▒ca provide etmek istedi─činiz de─čerin bir Future'─▒n─▒ sa─čl─▒yorsunuz.
FutureProvider, Future'─▒n ne zaman tamamland─▒─č─▒n─▒ dinler ve ard─▒ndan Consumerlar─▒ widget'lar─▒n─▒ yeniden olu┼čturmalar─▒ i├žin bilgilendirir.

A┼ča─č─▒daki kodda, kullan─▒c─▒ aray├╝z├╝ne baz─▒ initial datalar─▒ vermek i├žin bo┼č bir model kulland─▒m.
Ayr─▒ca 3 saniye sonra yeni bir model d├Ând├╝rme i┼člevi ekledim.
FutureProvider'─▒n bekledi─či ┼čey budur.

Temel Provider gibi, FutureProvider da modelin kendisindeki de─či┼čiklikleri dinlemez. A┼ča─č─▒daki kod 2 saniye sonra ÔÇťDo somethingÔÇŁ butonunu yaparak modeli de─či┼čtirir. 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);
  }
}
Enter fullscreen mode Exit fullscreen mode

Image description

FutureProvider, Consumer'a Future<MyModel> tamamland─▒ktan sonra yeniden olu┼čturmas─▒n─▒ s├Âyler.

Uygulamay─▒ ba┼člang─▒├ž de─čerleriyle yeniden olu┼čturmak i├žin hot restart'a bas─▒n.

"Do something" butonuna basman─▒n, Future tamamland─▒ktan sonra bile kullan─▒c─▒ aray├╝z├╝n├╝ g├╝ncellemedi─čini unutmay─▒n.
Bu t├╝r bir i┼člevsellik istiyorsan─▒z, son b├Âl├╝mdeki ChangeNotifierProvider'─▒ kullan─▒n.

FutureProvider i├žin kullan─▒m durumunuz, bir dosyadan veya a─čdan baz─▒ verileri okumak olabilir.Ancak bunu bir FutureBuilder ile de yapabilirsiniz.Uzman olmayan g├Âr├╝┼č├╝me g├Âre, FutureProvider bir FutureBuilder'dan ├žok daha kullan─▒┼čl─▒ de─čil.Bir sa─člay─▒c─▒ya ihtiyac─▒m olursa, muhtemelen bir ChangeNotifierProvider kullan─▒rd─▒m ve bir sa─člay─▒c─▒ya ihtiyac─▒m yoksa, muhtemelen bir FutureBuilder kullan─▒rd─▒m.
Yine de bir yorum eklemek isterseniz bunu g├╝ncellemekten memnuniyet duyar─▒m.

StreamProvider

StreamProvider, temel olarak StreamBuilder'─▒n etraf─▒ndaki bir sar─▒c─▒d─▒r. Bir ak─▒┼č sa─člars─▒n─▒z ve ard─▒ndan ak─▒┼čta bir olay oldu─čunda Consumer'lar yeniden olu┼čturulur. Kurulum, yukar─▒daki FutureProvider'a ├žok benzer.

StreamProvider modelin kendisindeki de─či┼čiklikleri dinlemez.
Yaln─▒zca ak─▒┼čtaki 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);
  }
}
Enter fullscreen mode Exit fullscreen mode

Image description

StreamProvider, Consumer'a yeni bir stream eventi (ak─▒┼č olay─▒) oldu─čunda yeniden olu┼čturmas─▒n─▒ s├Âyler.

Uygulamay─▒ ba┼člang─▒├ž de─čerleriyle yeniden olu┼čturmak i├žin hot restart a bas─▒n.

"Do something" d├╝─čmesine basman─▒n kullan─▒c─▒ aray├╝z├╝n├╝ g├╝ncellemedi─čini unutmay─▒n. Bu t├╝r bir i┼člevsellik istiyorsan─▒z, sadece ChangeNotifierProvider kullan─▒n. Asl─▒nda, model nesnenizde bir ak─▒┼č olabilir ve sadece notifyListeners()'─▒ ├ža─č─▒rabilirsiniz.
Bu durumda bir StreamProvider'a hi├ž ihtiyac─▒n─▒z olmaz.

ValueListenableProvider

ValueListenableProvider'─▒ immutable state model nesnesi ile kullanabilirsiniz ve de─či┼čmezli─čin (immutability) baz─▒ avantajlar─▒ vard─▒r.

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

ValueListenableProvider ile i├žindeki de─či┼čiklikleri dinleyebilirsiniz. Ancak, kullan─▒c─▒ aray├╝z├╝nden model ├╝zerinde bir method ├ža─č─▒rmak istiyorsan─▒z, modeli de sa─člaman─▒z gerekir.
Bu nedenle, a┼ča─č─▒daki kodda bir Provider'─▒n, MyModel'deki ValueNotifier'─▒ ValueListenableProvider'a veren bir Consumer'a MyModel sa─člad─▒─č─▒n─▒ g├Ârebilirsiniz.

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);
  }
}
Enter fullscreen mode Exit fullscreen mode

Image description

"Do something" butonuna basmak, ValueListenableProvider sayesinde "Hello"nun "Goodbye" olarak de─či┼čmesini sa─člar.

Widget a─čac─▒n─▒n en ├╝st├╝nde bir Consumer yerine Provider.of<MyModel>(context, listen: false) kullanmak muhtemelen daha iyi olur. Aksi takdirde, her seferinde t├╝m a─čac─▒ yeniden in┼ča ederiz.

Provider<MyModel>, myModel'i hem ValueListenableProvider'a hem de "Do something" d├╝─čmesinin kapanmas─▒na verir.

ListenableProvider

Bunu yaln─▒zca kendi ├Âzel provider'─▒n─▒z─▒ olu┼čturman─▒z gerekiyorsa kullan─▒rs─▒n─▒z.

MultiProvider

┼×imdiye kadar ki ├Ârneklerimiz yaln─▒zca bir model nesnesi kulland─▒.
─░kinci t├╝r bir model nesnesi sa─člaman─▒z gerekiyorsa, providerlar─▒ i├ž i├že yerle┼čtirebilirsiniz (yukar─▒daki ValueListenableProvider ├Ârne─činde yapt─▒─č─▒m gibi). Ancak, i├ž i├že kullan─▒m da─č─▒n─▒kt─▒r. Bunu yapman─▒n daha d├╝zg├╝n bir yolu, bir MultiProvider kullanmakt─▒r.

A┼ča─č─▒daki ├Ârnekte, iki ChangeNotifierProviders ile sa─članan iki farkl─▒ model vard─▒r.

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();
  }
}
Enter fullscreen mode Exit fullscreen mode

Image description

─░lk "Do something" d├╝─čmesine basmak, "Hello"yu "Goodbye" olarak de─či┼čtirecektir. ─░kinci ÔÇťDo somethingÔÇŁ d├╝─čmesine basmak ÔÇť0ÔÇŁ─▒ ÔÇť5ÔÇŁ olarak de─či┼čtirecektir.

Bununla tek ChangeNotifierProvider aras─▒nda pek bir fark yoktur.
Farkl─▒ Consumer'lar─▒n do─čru modeli alma yolu, g├Âsterdikleri t├╝re g├Âredir. Yani, Consumer<MyModel>, MyModel'i al─▒r ve Consumer<AnotherModel>, AnotherModel'i al─▒r.

ProxyProvider

Ya sa─člamak istedi─činiz iki modeliniz varsa, ancak modellerden biri di─čerine ba─čl─▒ysa?
Bu durumda bir ProxyProvider kullanabilirsiniz.
Bir ProxyProvider de─čeri bir providerdan al─▒r ve ba┼čka bir provider'a enjekte edilmesini sa─člar.

Bir ProxyProvider kurma ┼čekliniz ilk ba┼čta kafa kar─▒┼čt─▒r─▒c─▒ olabilir, bu y├╝zden bununla ilgili k├╝├ž├╝k bir a├ž─▒klama eklememe izin verin.

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

Temel ProxyProvider'─▒n iki t├╝r├╝ vard─▒r. Birinci tip, ikinci tipin ba─čl─▒ oldu─ču ┼čeydir. Yani, ba┼čka bir Provider taraf─▒ndan zaten sa─članm─▒┼č olan bir modeldir. G├╝ncelleme kapan─▒┼č─▒nda ikinci model tipine enjekte edilir. ├ť├ž├╝nc├╝ parametre (anotherModel) ├Ânceki yerle┼čik de─čeri saklar, ancak bunu burada kullanm─▒yoruz. Sadece myModel'i AnotherModel'in yap─▒c─▒s─▒na 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');
  }
}
Enter fullscreen mode Exit fullscreen mode

Image description

Metin ÔÇťHelloÔÇŁ ile ba┼člar.

ÔÇťDo somethingÔÇŁ d├╝─čmesine bast─▒─č─▒n─▒zda, MyModel metni ÔÇťGoodbyeÔÇŁ olarak de─či┼čtirir. MyModel dinleyicisini (ChangeNotifierProvider) bilgilendirir ve kullan─▒c─▒ aray├╝z├╝ yeni metinle yeniden olu┼čturulur.

"Do something else" d├╝─čmesine bast─▒─č─▒n─▒zda, AnotherModel MyModel'i (ProxyProvider taraf─▒ndan enjekte edilmi┼čtir) al─▒r ve metnini "See you later" olarak de─či┼čtirir. MyModel dinleyicilerine de─či┼čiklikleri bildirdi─či i├žin, kullan─▒c─▒ aray├╝z├╝ tekrar g├╝ncellenir. AnotherModel'in de─či┼čen kendi verileri olsayd─▒, ProxyProvider de─či┼čiklikleri dinlemedi─činden UI g├╝ncellenmezdi. Bunun i├žin bir ChangeNotifierProxyProvider gerekir.

Provider builder ve value constructors

Bitirmeden ├Ânce, Provider'─▒ kullanmay─▒ ├Â─črenirken kafam─▒ kar─▒┼čt─▒ran bir ┼čeyi daha a├ž─▒klamak istiyorum.
Provider widget ├Â─čelerinin ├žo─ču (t├╝m├╝ de─čilse de) iki t├╝r constructor'a sahiptir. basic constructor, model nesnenizi olu┼čturdu─čunuz bir olu┼čturma i┼člevi al─▒r. Bunu yukar─▒daki ├Ârneklerin ├žo─čunda yapt─▒k.

Provider<MyModel>(
  create: (context) => MyModel(),
  child: ...
)
Enter fullscreen mode Exit fullscreen mode

MyModel Nesnenin create fonksiyonunda olu┼čturuldu─čunu g├Ârebilirsiniz .

Nesneniz zaten olu┼čturulduysa ve yaln─▒zca ona bir referans sa─člamak istiyorsan─▒z, value adl─▒ named (adland─▒r─▒lm─▒┼č) constructor'─▒ kullanabilirsiniz:

final myModel = MyModel();
...
Provider<MyModel>.value(
    value: myModel, 
    child: ...
)
Enter fullscreen mode Exit fullscreen mode

Burada MyModel daha ├Ânce olu┼čturuldu ve sadece referans olarak iletildi. A─čdan veri y├╝klemek i├žin modelde bir y├Ântemi ├ža─č─▒rabilmeniz i├žin modelinizi initState() y├Ânteminde ba┼člatm─▒┼č olsayd─▒n─▒z bunu yapard─▒n─▒z.

resource

Top comments (2)

Collapse
 
sahinmehmetemre profile image
Mehmet ┼×ahin

Kafa kar─▒┼č─▒kl─▒─č─▒m─▒ gideren yaz─▒n─▒z i├žin te┼čekk├╝r ederim. G├╝zel bir ├žal─▒┼čma olmu┼č, elinize sa─čl─▒k.

Collapse
 
gulsenkeskin profile image
G├╝lsen Keskin

Ben te┼čekk├╝r ederim. ─░┼činize yarad─▒ysa ne mutlu :D