مثال کاربردی فلاتر برای مدیریت استیت با پکیج Provider – بخش سوم

دوستان لینک بخش اول و بخش دوم تقدیم حضورتون.

خب بخش سوم رو شروع میکنیم که تقریبا مهم ترین بخشه و ترجمه ی قسمت نحوه کار با Provider رو میبینیم.

قبل از کار کردن با provider ، فراموش نکنید که حتما آنرا در بخش dependency در pubspec.yaml اضافه کنید.

آپدیت: عناوین تیتر هارو لینک دادم به رفرنس فلاتر. بعد از کلیک 5 ثانیه صبر کنید و دکمه skip سمت راست صفحه رو کلیک کنید.

حالا میتوانید پکیج را به صورت زیر ایمپورت و شروع به ساختن اپ کنید:

import 'package:provider/provider.dart';

در provider نیازی به نگرانی درباره callback یا InheritedWidgets نیست. اما شما باید مفاهیم سه گانه زیر را متوجه شوید:

  • ChangeNotifier
  • ChangeNotifierProvider
  • Consumer

ChangeNotifier

ChangeNotifier یک کلاس ساده از Flutter SDK است که تغییرات اعلانها را به شنونده ها(Listeners) فراهم میکند. به عبارت دیگر، اگر چیزی ChangeNotifier باشد، شما متوجه تغییرات میشوید. (آن مانند یک فرم قابل مشاهده است.)

در provider ، یکی از راه های کپسوله سازی استیت برنامه شما ChangeNotifier است. برای هر برنامه ی ساده، با ChangeNotifier از پس آن برمی آیید. در موارد پیچیده، شما چندین مدل خواهید داشت، و بنابراین چندین ChangeNotifier. (شما در کل برای استفاده از ChangeNotifier نیازی به provider نخواهید نداشت اما کار کردن با آن کلاس بسیار است.)

در مثال اپلیکیشن فروشگاهی ما، میخواهیم استیت های سبد خرید را در یک ChangeNotifier مدیریت کنیم. ما یک کلاس جدید میسازیم که آنرا گسترش میدهد، مانند مثال زیر:

تنها کدی که برای ChangeNotifier خاص است، فراخوانی notifyListener() است. هرزمان که مدل به گونه ای تغییر کرد که ممکن است رابط کاربری برنامه شما تغییر کند، این متد فراخوانی میشود. هرچیز دیگر در CartModel خود مدل و منطق تجاری آن است.(نویسنده: اینجاشو نفهمیدم :/  Everything else in CartModel is the model itself and its business logic.)

ChangeNotifier قسمتی از flutter:foundation است و به هیچ کلاس سطح بالاتر در فلاتر بستگی ندارد. به راحتی تست پذیر است( حتی نیازی به ویجت تست برای آن ندارید.) به عنوان مثال، در اینجا یک تست واحد(unit) از CartModel داریم:


ChangeNotifierProvider

ChangeNotifierProvider ویجتی است که یک نمونه از ChangeNotifier به فرزندانش آماده میکند. این ویجت از پکیج Provider است. ما در حال حاضر میدانیم کجا باید ChangeNotifierProvider  را قرار دهیم: بالاتر از ویجت هایی که نیاز به دسترسی به آن دارند.در مورد CartModel ، جایی بالاتر از MyCart و MyCatalog . شما نمیخواهید ChangeNotifierProvider  را بالاتر از جایی که به آن نیاز دارید قرار دهید.(چون نمیخواهید محدوده را اشغال کنید) اما در مثال ما، تنها ویجتی که بالای هردو ویجت MyCart  و MyCatalog قرار میگیرد، MyApp است.

توجه داشته باشید که ما یک سازنده ای(builder) تعریف میکنیم که نمونه جدیدی از CartModel میسازد. ChangeNotifierProvider به اندازه کافی هوشمند است که دوباره CartModel را نسازد مگر اینکه کاملا ضروری باشد. و همچین آن، به صورت اتوماتیک dispose() را در CartModel زمانیکه که دیگر نمونه دیگر مورد نیاز نیست فراخوانی میکند.

اگر شما بیشتر از یک کلاس میخواهید فراهم(provide) کنید، میتوانید از MultiProvider استفاده کنید.

Consumer

حالا که CartModel برای ویجت ها ی اپ ما با استفاده از ChangeNotifierProvider  ارائه(provide) شده، میتوانیم از آن استفاده کنیم.

این کار با استفاده از Consumer انجام میشود. (–معنی لغوی: مصرف کننده–)

ما باید نوع مدلی که میخواهیم به آن دسترسی داشته باشیم را مشخص کنیم. در این مورد ما CartModel را میخواهیم، بنابراین مینویسیم: Consumer<CartModel> . اگر آنرا مشخص نکنید( <CartModel> )، پکیج provider نمیتواند به شما کمک کند؛ provider بر اساس انواع است و بدون نوع(type) نمیداند شما چه میخواهید.

تنها آرگومانی که Consumer میخواهد، builder است. Builder یک فانکشن است که هر زمان که ChangeNotifier تغییر کند، فراخوانی میشود. (به عبارت دیگر وقتی شما notifyListeners() را در مدل خود صدا میزنید، تمام متد های builder همه ویجت های Consumer مربوطه صدا زده میشود.)

builder با سه آرگومان فراخوانی میشود. اول context است، که همچین شما در تمام build متد ها دریافت میکنید.

دومین آرگومان تابع build ، نمونه ی ChangeNotifier است. این همان چیزی است که ما در وهله ی اول میخواستیم. میتوانید از داده های موجود در مدل استفاده کنید تا تعریف کنید که رابط کاربری در هر نقطه مشخص چگونه باشد.

سومین آرگومان child است، که برای بهینه سازی است. اگر زیر درخت بزرگی زیر Consumer دارید، تغییرات مدل تغییر نمیکند. شما میتوانید یکبار آنرا بسازید و از طریق build دریافتش کنید.

این بهترین تمرین است که ویجت های Consumer را تا حد امکان در عمق درخت قرار دهید. شما نمیخواهید بخش های بزرگی از UI را بدلیل اینکه برخی از جزئیات در جایی تغییر کرده است دوباره بسازید(rebuild).

در عوض:

Provider.of

گاهی، واقعا نیازی به داده های مدل برای تغییر رابط کاربری ندارید اما همچنان باید به آن دسترسی داشته باشید. برای مثال، یک دکمه ClearCart برای پاک کردن قسمتی از آیتم های سبدخرید نیاز به اجازه کاربر دارد، نیازی به نمایش محتویات سبدخرید نیست، فقط باید متد clear() را فراخوانی کند.

میتوانستیم از Consumer<CartModel> استفاده کنیم، اما این کار بیهوده ای خواهد بود. ما از فریمورک میخواهیم ویجتی را بازسازی کند که نیازی به بازسازی ندارد.

برای انجام این کار، میتوانیم از Provider.of استفاده کنیم، همراه یک پارامتر listen که روی false تنظیم شده.

استفاده از خط بالا در یک build هنگام صدازدن notifyListeners باعث بازسازی یک ویجت نمیشود.

همه را کنار هم بگذارید

شما میتوانید مثالی که این مقاله توضیح داده شده را در این لینک بررسی کنید. اگر چیز ساده تری میخواهید، این اپ شمارنده ی ساده را که با provider ساخته شده ببینید.

با دنبال کردن این مقالات، شما توانایی خود را برای ایجاد اپلیکیشن های کاربردی مبتنی بر state بسیار بهبود بخشیده اید.سعی کنید یک اپلیکیشن همراه با provider بسازید تا بر این مهارت ها مسلط شوید.

(اگه این مقاله به دردت خورد با زرین پال یا ایدی پی حمایتم کن یا از کافه ت برام یه کافه بخر😉)

دوستان عزیز این بخش هم تمام شد. قسمت بعدی هم لیست ابزاری های مدیریت state رو قرار داده که میتونید از لینک زیر بهش دسترسی داشته باشید.

List of state management approaches

لینک دسترسی به بخش اول و بخش دوم مقاله .

سیدعباس حسینی

نویسنده: AbbasHoseini

به دنبال خلق رویام تو دنیای برنامه نویسی پیرو دنیای آزاد

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد.