Flutter Provider Türleri 💫 🌌 ✨
Tags: flutter, provider, dart, statemanagement
Published: 2022-01-29 22:49:35



Not: Bu yazı [Flutter Community](https://medium.com/flutter-community/making-sense-all-of-those-flutter-providers-e842e18f45dd) tarafından paylaşılan makalenin Türkçe çevirisi niteliğini taşır. Orijinal içeriğe linkten ulaşabilirsiniz.


## 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ni6z0bxvgkx155jktp0d.png)

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

          ],
        ),
      ),
    );
  }
}
```

Provider paketini pubspec.yaml dosyanıza ekleyin:

```
dependencies:
  provider: ^6.0.2
```

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);
  }
}
```


```
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 çalıştırdığınızda aşağıdaki sonucu alırsınız:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mpxlp1mec87nedekxz0n.png)
 
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();
  }
}
```

Şimdi “Do something” düğmesine bastığınızda, metin “Hello” dan “Goodbye” a dönüşür.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z163aq179xchesp5vovs.png)

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


## 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);
  }
}
```
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gbpexn46vglkyy2mqos7.png) 
 
`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);
  }
}
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/azirmfpqmg6q2of99hyc.png)
 

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';
  }
}
```

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);
  }
}
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7x5s64grvgasltxg0grr.png)


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

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/focod4jyzsafwc2h1yyc.png)

İ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),
    ),
  ],
```

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');
  }
}
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m991nyubxaw9m6fsmybo.png)

 

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: ...
)
```

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: ...
)
```

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](https://medium.com/flutter-community/making-sense-all-of-those-flutter-providers-e842e18f45dd)