DEV Community

Cover image for Flutter Consumer Widget ­čĺź ­čîî ÔťĘ
G├╝lsen Keskin
G├╝lsen Keskin

Posted on

Flutter Consumer Widget ­čĺź ­čîî ÔťĘ

Consumer widget'─▒n iki ana amac─▒ vard─▒r:
BuildContext'imiz olmad─▒─č─▒nda ve bu nedenle Provider.of'u kullanamad─▒─č─▒m─▒zda provider'dan bir de─čer al─▒nmas─▒na izin verir.

Bu senaryo genellikle, a┼ča─č─▒daki ├Ârnekte oldu─ču gibi, provider'─▒ olu┼čturan widget ├Â─česi ayn─▒ zamanda consumer'lardan biri oldu─čunda ger├žekle┼čir:

@override
Widget build(BuildContext context) {
  return ChangeNotifierProvider(
    create: (_) => Foo(),
    child: Text(Provider.of<Foo>(context).value),
  );
}
Enter fullscreen mode Exit fullscreen mode

Provider.of, provider'─▒n─▒n atas─▒ olan bir BuildContext ile ├ža─čr─▒ld─▒─č─▒ndan, bu ├Ârnek bir ProviderNotFoundException olu┼čturacakt─▒r.

Bunun yerine, Provider.of'u kendi BuildContext'i ile ├ža─č─▒racak olan Consumer widget ├Â─česini kullanabiliriz.

Consumer kullanarak ├Ânceki ├Ârne─či ┼č├Âyle yazabiliriz:

@override
Widget build(BuildContext context) {
  return ChangeNotifierProvider(
    create: (_) => Foo(),
    child: Consumer<Foo>(
      builder: (_, foo, __) => Text(foo.value),
    },
  );
}
Enter fullscreen mode Exit fullscreen mode

Bu, ProviderNotFoundException olu┼čturmaz ve Text'i do─čru ┼čekilde olu┼čturur. Ayr─▒ca, foo de─čeri de─či┼čti─činde Text'i de g├╝nceller.

Bu durum daha ayr─▒nt─▒l─▒ yeniden olu┼čturmalar sa─člayarak performans optimizasyonuna yard─▒mc─▒ olur.

Listen: false Provider.of'a ge├žirilmedi─či s├╝rece, Provider.of'a ge├žirilen BuildContext ile ili┼čkili widget ├Â─česi, elde edilen de─čer de─či┼čti─činde yeniden olu┼čturulur. Bu beklenen davran─▒┼čt─▒r, ancak bazen gerekenden daha fazla widget'─▒ yeniden olu┼čturabilir.

├ľrne─čin:

 @override
 Widget build(BuildContext context) {
   return FooWidget(
     child: BarWidget(
       bar: Provider.of<Bar>(context),
     ),
   );
 }
Enter fullscreen mode Exit fullscreen mode

Yukar─▒daki kodda, yaln─▒zca BarWidget Provider.of taraf─▒ndan d├Ând├╝r├╝len de─čere ba─čl─▒d─▒r. Ancak Bar de─či┼čti─činde, hem BarWidget hem de FooWidget yeniden olu┼čturulacakt─▒r.

─░deal olarak, yaln─▒zca BarWidget yeniden olu┼čturulmal─▒d─▒r. Bunu ba┼čarmak i├žin ├ž├Âz├╝m Consumer kullanmakt─▒r.

Bunu yapmak i├žin, yaln─▒zca provider'a ba─čl─▒ olan widget ├Â─čelerini bir Consumer'a sarar─▒z:

 @override
 Widget build(BuildContext context) {
   return FooWidget(
     child: Consumer<Bar>(
       builder: (_, bar, __) => BarWidget(bar: bar),
     ),
   );
 }
Enter fullscreen mode Exit fullscreen mode

Bu durumda, Bar g├╝ncellenirse yaln─▒zca BarWidget yeniden olu┼čturulur.

Ama ya bir provider'a ba─čl─▒ olan FooWidget ise? ├ľrne─čin:

 @override
 Widget build(BuildContext context) {
   return FooWidget(
     foo: Provider.of<Foo>(context),
     child: BarWidget(),
   );
 }
Enter fullscreen mode Exit fullscreen mode

Consumer ve iste─če ba─čl─▒ child arg├╝man─▒n─▒ kullanarak bu t├╝r bir senaryoyu ele alabiliriz:

 @override
 Widget build(BuildContext context) {
   return Consumer<Foo>(
     builder: (_, foo, child) => FooWidget(foo: foo, child: child),
     child: BarWidget(),
   );
 }
Enter fullscreen mode Exit fullscreen mode

Bu ├Ârnekte, BarWidget builder'─▒n d─▒┼č─▒nda olu┼čturulmu┼čtur. Ard─▒ndan, BarWidget ├Ârne─či builder'a son parametre olarak iletilir.

Bu, Builder yeni de─čerlerle yeniden ├ža─čr─▒ld─▒─č─▒nda, yeni bir BarWidget ├Ârne─činin olu┼čturulmayaca─č─▒ anlam─▒na gelir. Bu da, Flutter'─▒n BarWidget'─▒ yeniden olu┼čturmas─▒ gerekmedi─čini bilmesini sa─člar. Bu nedenle, b├Âyle bir yap─▒land─▒rmada, Foo de─či┼čirse yaln─▒zca FooWidget yeniden olu┼čturulur.

Not:
Consumer widget'─▒, MultiProvider i├žinde de kullan─▒labilir. Bunu yapmak i├žin, olu┼čturucuya iletilen child'─▒, olu┼čturdu─ču widget a─čac─▒nda d├Ând├╝rmesi gerekir.

MultiProvider(
  providers: [
    Provider(create: (_) => Foo()),
    Consumer<Foo>(
      builder: (context, foo, child) =>
        Provider.value(value: foo.bar, child: child),
    )
  ],
);
Enter fullscreen mode Exit fullscreen mode

Consumer widget'─▒n─▒n tek gerekli arg├╝man─▒ builder'd─▒r.
Builder, ChangeNotifier de─či┼čti─činde ├ža─čr─▒lan bir fonksiyondur.
Ba┼čka bir deyi┼čle, modelinizde notifyListeners() ├Â─česini ├ža─č─▒rd─▒─č─▒n─▒zda, kar┼č─▒l─▒k gelen t├╝m Consumer widget ├Â─čelerinin t├╝m builder methodlar─▒ ├ža─čr─▒l─▒r.

Builder ├╝├ž arg├╝manla ├ža─čr─▒l─▒r. ─░lki, her derleme y├Ânteminde de ald─▒─č─▒n─▒z context'dir.

Builder fonksiyonunun ikinci arg├╝man─▒, ChangeNotifier ├Ârne─čidir(instance).

├ť├ž├╝nc├╝ arg├╝man, optimizasyon i├žin orada olan child'd─▒r. Consumer'─▒n─▒z─▒n alt─▒nda model de─či┼čti─činde de─či┼čmeyen b├╝y├╝k bir widget alt a─čac─▒n─▒z varsa, onu bir kez olu┼čturabilir ve builder'dan (olu┼čturucudan) ge├žirebilirsiniz.

return Consumer<CartModel>(
  builder: (context, cart, child) => Stack(
    children: [
    // SomeExpensiveWidget'─▒ her seferinde yeniden olu┼čturmadan burada kullan─▒n.
      if (child != null) child,
      Text("Total price: ${cart.totalPrice}"),
    ],
  ),
// Pahal─▒ widget'─▒ burada olu┼čturun.
  child: const SomeExpensiveWidget(),
);
Enter fullscreen mode Exit fullscreen mode

Consumer widget'lar─▒n─▒z─▒ a─čac─▒n m├╝mk├╝n oldu─čunca derinlerine yerle┼čtirmek en iyi uygulamad─▒r. Baz─▒ ayr─▒nt─▒lar de─či┼čti diye kullan─▒c─▒ aray├╝z├╝n├╝n b├╝y├╝k b├Âl├╝mlerini yeniden olu┼čturmak istemezsiniz.

// BUNU YAPMA
return Consumer<CartModel>(
  builder: (context, cart, child) {
    return HumongousWidget(
      // ...
      child: AnotherMonstrousWidget(
        // ...
        child: Text('Total price: ${cart.totalPrice}'),
      ),
    );
  },
);
Enter fullscreen mode Exit fullscreen mode

Bunun yerine:

// BUNU YAP
return HumongousWidget(
  // ...
  child: AnotherMonstrousWidget(
    // ...
    child: Consumer<CartModel>(
      builder: (context, cart, child) {
        return Text('Total price: ${cart.totalPrice}');
      },
    ),
  ),
);
Enter fullscreen mode Exit fullscreen mode

References:
https://docs.flutter.dev/development/data-and-backend/state-mgmt/simple
https://pub.dev/documentation/provider/latest/provider/Consumer-class.html
https://flutterbyexample.com/lesson/finer-build-control-with-selector-1

Discussion (0)