FlutterFlutter · Chapterبەش 11 · Lectureوانە 11.5
FutureProvider and StreamProviderFutureProvider و StreamProvider
The lecture's to-do app in three steps: injecting the signed-in User with Provider (dependency injection) while a FutureBuilder loads the list, replacing the FutureBuilder with a FutureProvider (initialData, loading and catchError), and showing live data with a StreamProvider.
ئەرکەکانی وانەکە لە سێ هەنگاودا: تێخستنی چووە ژوورەوە بە Provider () لە کاتێکدا FutureBuilderـێک لیستەکە بار دەکات، گۆڕینەوەی FutureBuilder بە FutureProvider (initialData، بارکردن و catchError) و پیشاندانی دراوەی زیندوو بە StreamProvider.
What you will learnچی فێر دەبیت
- Inject a value that already exists with Provider.value and explain dependency injection in the to-do app.
- Replace a FutureBuilder with a FutureProvider and read the result with context.watch.
- Use initialData, a nullable type and catchError for loading and errors.
- Show live data from a Stream with a StreamProvider.
- Choose between FutureBuilder, FutureProvider, StreamProvider and ChangeNotifierProvider.
- نرخێک کە هەیە بە
Provider.valueتێبخەیت و لە ئەرکەکاندا ڕوون بکەیتەوە. - FutureBuilderـێک بە FutureProvider بگۆڕیتەوە و ئەنجامەکە بە
context.watchبخوێنیتەوە. initialData، جۆرێکی nullable وcatchErrorبۆ بارکردن و بەکار بهێنیت.- دراوەی زیندوو لە بە StreamProvider پیشان بدەیت.
- لە نێوان FutureBuilder، FutureProvider، StreamProvider و ChangeNotifierProviderـدا هەڵبژێریت.
Providers for data that arrives laterprovider بۆ دراوەیەک کە دواتر دەگات
Much of an app's data is not ready at once: a user loaded after sign-in, a to-do list from a server, live updates from a database. Dart has two types for that, which you met in Futures and async: a Future gives one value later, and a Stream gives many values over time. On a screen you showed them with FutureBuilder and StreamBuilder.
زۆربەی دراوەی یەکسەر ئامادە نییە: کە دوای بار دەکرێت، لیستی ئەرکەکان لە ، نوێکارییە زیندووەکان لە . Dart دوو جۆری بۆ ئەمە هەیە کە لە نرخەکانی داهاتوو و async بینیت: یەک نرخ دواتر دەدات و بە درێژایی کات چەندین نرخ دەدات. لەسەر شاشە بە FutureBuilder و StreamBuilder پیشانت دان.
The provider package has two providers for exactly these types. FutureProvider waits for a Future and gives its result to the widgets below; StreamProvider listens to a Stream and always gives the latest value. The lecture shows both in its to-do app, step by step.
provider دوو providerـی ڕێک بۆ ئەم جۆرانە هەیە. FutureProvider چاوەڕێی دەکات و ئەنجامەکەی دەدات بە ئەو لە خوارەوەن؛ StreamProvider گوێ لە دەگرێت و هەمیشە دوایین نرخ دەدات. وانەکە هەردووکیان لە ئەرکەکانیدا هەنگاو بە هەنگاو پیشان دەدات.
The lecture's to-do app: injecting the Userئەپی ئەرکەکانی وانەکە: تێخستنی User
The lecture starts from a to-do list whose app bar shows the signed-in user. Two services fetch the data: UserDataService.getUser(id) and TodoDataService.getTodoList(). The lecture keeps them in a service locator, one central place where the app finds its services. (A later lesson, Organising an MVVM Project: Folders, Services and get_it, builds a real service locator with the get_it package.) Here are the two services, returning fake data after a short wait, like a slow server:
وانەکە لە لیستێکی ئەرکەکانەوە دەست پێ دەکات کە ئەو پیشان دەدات کە چووەتە ژوورەوە. دوو دراوەکان دەهێنن: UserDataService.getUser(id) و TodoDataService.getTodoList(). وانەکە ئەمانە لە هەڵدەگرێت، یەک شوێنی ناوەندی کە تێدا دەدۆزێتەوە. (وانەیەکی دواتر، ڕێکخستنی پڕۆژەیەکی MVVM: فۆڵدەرەکان، خزمەتگوزارییەکان و get_it، بە get_it ڕاستەقینە دروست دەکات.) ئەمانە دوو ، کە دوای چاوەڕوانییەکی کورت دراوەی ساختە دەگەڕێننەوە، وەک خاو:
class User {
const User({required this.id, required this.name});
final int id;
final String name;
}
class Todo {
const Todo({required this.id, required this.title});
final int id;
final String title;
}
// The lecture's "service locator" holds services like these.
// They pretend to be a slow server: the data arrives later.
class UserDataService {
Future<User> getUser(int id) async {
await Future.delayed(const Duration(milliseconds: 500));
return User(id: id, name: 'Shilan');
}
}
class TodoDataService {
// One answer, later: a Future.
Future<List<Todo>> getTodoList() async {
await Future.delayed(const Duration(seconds: 1));
return const [
Todo(id: 1, title: 'Read chapter 8'),
Todo(id: 2, title: 'Revise for the quiz'),
Todo(id: 3, title: 'Buy a notebook'),
];
}
// Many answers over time: a Stream. Each value is the whole new list.
Stream<List<Todo>> watchTodoList() async* {
var todos = <Todo>[];
for (final title in ['Read chapter 8', 'Call Hana', 'Practise layouts']) {
await Future.delayed(const Duration(seconds: 1));
todos = [...todos, Todo(id: todos.length + 1, title: title)];
yield todos;
}
}
}In the lecture's first version, only the User uses Provider: it is fetched once at sign-in and injected above MaterialApp, so every screen can read it without creating it (that is dependency injection). The to-do list still uses a stateful widget and a FutureBuilder:
لە وەشانی یەکەمی وانەکەدا، تەنها User Provider بەکار دەهێنێت: یەک جار لە کاتی دەهێنرێت و لە سەرووی MaterialAppـەوە تێدەخرێت، بۆیە هەموو شاشەیەک دەتوانێت بیخوێنێتەوە بەبێ ئەوەی دروستی بکات (ئەمە پێی دەوترێت تێخستنی وابەستەیی). لیستی ئەرکەکان هێشتا و FutureBuilder بەکار دەهێنێت:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'todo_services.dart';
Future<void> main() async {
final user = await UserDataService().getUser(1); // sign-in finished
runApp(buildApp(user));
}
Widget buildApp(User user) {
// Only the User goes through Provider (dependency injection).
return Provider<User>.value(
value: user, // the object already exists, so .value is right
child: const MaterialApp(home: TodoListScreen()),
);
}
// The to-do list still uses a stateful widget and a FutureBuilder.
class TodoListScreen extends StatefulWidget {
const TodoListScreen({super.key});
@override
State<TodoListScreen> createState() => _TodoListScreenState();
}
class _TodoListScreenState extends State<TodoListScreen> {
late final Future<List<Todo>> _todos = TodoDataService().getTodoList();
@override
Widget build(BuildContext context) {
final user = Provider.of<User>(context); // injected, not created here
return Scaffold(
appBar: AppBar(title: Text("${user.name}'s to-dos")),
body: FutureBuilder<List<Todo>>(
future: _todos,
builder: (context, snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
return const Center(child: CircularProgressIndicator());
}
if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}'));
}
final todos = snapshot.data!;
return ListView.builder(
itemCount: todos.length,
itemBuilder: (context, i) => ListTile(title: Text(todos[i].title)),
);
},
),
);
}
}FutureBuilder at 0 s: spinner=true, rows=0, title="Shilan's to-dos" FutureBuilder after 1 s: spinner=false, rows=3
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 7
The user is loaded before the app starts, so it already exists…
پێش دەستپێکردنی بار دەکرێت، بۆیە پێشتر هەیە…
- Lineدێڕی 14
…and
.valueis the right constructor for an existing object.…و
.valueدروستە بۆ کە هەیە.- Lineدێڕی 28
The Future is made once, in the State object, not in
build.یەک جار دروست دەکرێت، لە ، نەک لە
buildـدا.- Lineدێڕی 32
The screen receives the user; it does not create it.
شاشەکە وەردەگرێت؛ دروستی ناکات.
FutureProvider: no more FutureBuilderFutureProvider: چیتر FutureBuilder نییە
In the next step, the to-do list moves into a provider too. A FutureProvider takes a function that creates the Future, waits for it, and makes the result available to the widgets below. The screen no longer needs a State object or a FutureBuilder: it simply watches a List<Todo>.
لە هەنگاوی داهاتوودا، لیستی ئەرکەکانیش دەچێتە ناو providerـێکەوە. FutureProvider وەردەگرێت کە دروست دەکات، چاوەڕێی دەکات و ئەنجامەکەی بەردەست دەکات بۆ ئەو لە خوارەوەن. شاشەکە چیتر پێویستی بە یان FutureBuilder نییە: بە سادەیی List<Todo>ـێک watch دەکات.
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'todo_services.dart';
Future<void> main() async {
final user = await UserDataService().getUser(1);
runApp(buildApp(user));
}
Widget buildApp(User user) {
return MultiProvider(
providers: [
Provider<User>.value(value: user),
FutureProvider<List<Todo>>(
create: (_) => TodoDataService().getTodoList(),
initialData: const [], // shown until the Future completes
),
],
child: const MaterialApp(home: TodoListScreen()),
);
}
// No State object and no FutureBuilder any more.
class TodoListScreen extends StatelessWidget {
const TodoListScreen({super.key});
@override
Widget build(BuildContext context) {
final user = context.watch<User>();
final todos = context.watch<List<Todo>>(); // [] first, then the list
return Scaffold(
appBar: AppBar(title: Text("${user.name}'s to-dos")),
body: ListView.builder(
itemCount: todos.length,
itemBuilder: (context, i) => ListTile(title: Text(todos[i].title)),
),
);
}
}FutureProvider at 0 s: rows=0 (initialData) FutureProvider after 1 s: rows=3
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 16
The provider calls the service once and listens to the Future.
providerـەکە یەک جار بانگی دەکات و گوێ لە دەگرێت.
- Lineدێڕی 17
Required: the value the screen gets before the Future completes.
پێویستە: ئەو نرخەی شاشەکە پێش تەواوبوونی وەری دەگرێت.
- Lineدێڕی 31
First
[], then, one second later, the three to-dos: the screen is rebuilt once.سەرەتا
[]، پاشان، چرکەیەک دواتر، سێ ئەرکەکە: شاشەکە یەک جار دووبارە دروست دەکرێتەوە.
FutureProvider: no more FutureBuilderFutureProvider: چیتر FutureBuilder نییە
Loading and errors with FutureProviderچاوەڕوانی و هەڵەکان لەگەڵ FutureProvider
An empty list as initialData hides the difference between “still loading” and “there are no to-dos”. Give the provider a nullable type and initialData: null: then null means loading. A FutureBuilder had an error branch; FutureProvider has catchError, a callback that turns an error into a value. Without it, a failing Future is reported as an error in your app:
لیستێکی بەتاڵ وەک initialData جیاوازیی نێوان «هێشتا بار دەکرێت» و «هیچ ئەرکێک نییە» دەشارێتەوە. جۆرێکی nullable و initialData: null بدە بە providerـەکە: ئەو کاتە null واتە هێشتا بار دەکرێت. FutureBuilder لقێکی هەبوو؛ FutureProvider catchErrorـی هەیە، کە دەگۆڕێت بۆ نرخێک. بەبێ ئەو، شکستخواردوو وەک لە ڕادەگەیەنرێت:
Widget buildApp() {
return FutureProvider<List<Todo>?>(
create: (_) => TodoDataService().getTodoList(),
initialData: null, // null means "still loading"
catchError: (_, error) => const [], // the Future failed: use an empty list
child: const MaterialApp(home: TodoListScreen()),
);
}class TodoListScreen extends StatelessWidget {
const TodoListScreen({super.key});
@override
Widget build(BuildContext context) {
final todos = context.watch<List<Todo>?>(); // the same nullable type
Widget body;
if (todos == null) {
body = const Center(child: CircularProgressIndicator()); // loading
} else if (todos.isEmpty) {
body = const Center(child: Text('No to-dos.'));
} else {
body = ListView(
children: [for (final t in todos) ListTile(title: Text(t.title))],
);
}
return Scaffold(appBar: AppBar(title: const Text('My to-dos')), body: body);
}
}nullable at 0 s: spinner=true nullable after 1 s: spinner=false, rows=3 with catchError: "No to-dos." shown: 1 without catchError: An exception was throw by Future<List<Todo>?> listened by / FutureProvider<List<Todo>?>, but no `catchError` was provided. / … / Exception:
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 6
Read with exactly the same type,
List<Todo>?, or the provider is not found.ڕێک بە هەمان جۆر بیخوێنەرەوە،
List<Todo>?، ئەگەرنا providerـەکە نادۆزرێتەوە.
| Pointخاڵ | FutureBuilder | FutureProvider |
|---|---|---|
| Where it livesلە کوێ دەژی | Inside one screen's buildلەناو buildـی یەک شاشەدا | Above the screens, in the treeلە سەرووی شاشەکانەوە، لە |
| Who can use the resultکێ دەتوانێت ئەنجامەکە بەکار بهێنێت | Only its builderتەنها builderـەکەی | Every widget below, by typeهەموو خوارەوە، بەپێی جۆر |
| Waitingچاوەڕوانی | snapshot.connectionState | initialData (for example null)initialData (بۆ نموونە null) |
| Errors | snapshot.hasError | catchError |
| Good forباشە بۆ | One screen, full control of every stateیەک شاشە، کۆنترۆڵی تەواوی هەموو دۆخێک | Data many screens shareدراوەیەک کە چەند شاشەیەک هاوبەشی دەکەن |
StreamProvider: live dataStreamProvider: دراوەی زیندوو
The lecture's last tree is the same as the FutureProvider one, with one change: the data service returns a Stream<List<Todo>>, and a StreamProvider sits in the tree. Each time the stream sends a new list, the provider exposes it and the screen is rebuilt. Typical sources are a Firestore query that sends a fresh list on every change (see Reading live with StreamBuilder), the battery level, or the sign-in state.
دوایین وانەکە وەک هی FutureProviderـە، بە یەک گۆڕانەوە: دراوەکە Stream<List<Todo>>ـێک دەگەڕێنێتەوە و StreamProviderـێک لە دادەنرێت. هەر جارێک لیستێکی نوێ بنێرێت، providerـەکە دەیدات و شاشەکە دووبارە دروست دەکرێتەوە. سەرچاوە باوەکان: Firestore کە لە هەر گۆڕانێکدا لیستێکی تازە دەنێرێت (بڕوانە خوێندنەوەی زیندوو بە StreamBuilder)، ئاستی باتری، یان دۆخی .
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'todo_services.dart';
void main() => runApp(buildApp(TodoDataService().watchTodoList()));
Widget buildApp(Stream<List<Todo>> todoStream) {
return StreamProvider<List<Todo>>(
create: (_) => todoStream,
initialData: const [], // until the first list arrives
child: const MaterialApp(home: LiveTodoScreen()),
);
}
class LiveTodoScreen extends StatelessWidget {
const LiveTodoScreen({super.key});
@override
Widget build(BuildContext context) {
// Rebuilt every time the stream sends a new list.
final todos = context.watch<List<Todo>>();
return Scaffold(
appBar: AppBar(title: Text('Live to-dos (${todos.length})')),
body: todos.isEmpty
? const Center(child: Text('No to-dos yet.'))
: ListView.builder(
itemCount: todos.length,
itemBuilder: (context, i) => ListTile(
leading: CircleAvatar(child: Text('${todos[i].id}')),
title: Text(todos[i].title),
),
),
);
}
}after 0 s: rows=0 after 1 s: rows=1 after 2 s: rows=2 after 3 s: rows=3
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 10
The provider subscribes to the stream and cancels the subscription when it leaves the tree.
providerـەکە بەشداری دەکات و کاتێک لە دەردەچێت بەشدارییەکە هەڵدەوەشێنێتەوە.
- Lineدێڕی 11
Required here too: the value before the first event.
لێرەشدا پێویستە: نرخەکە پێش یەکەم .
- Lineدێڕی 22
The same
watchas before: the screen does not know whether a Future or a Stream is behind it.هەمان
watchـی پێشوو: شاشەکە نازانێت یان لە پشتییەوەیە.
![Animation in four frames. Left: a pipe labelled watchTodoList(): Stream<List<Todo>> and StreamProvider(initialData: const []); right: a phone titled 'Live to-dos'. Frame 1: the pipe is empty, the phone says 'No to-dos yet.', rebuilds so far: 0. Frame 2: a value [1 item] arrives, the phone shows 'Read chapter 8' highlighted, title Live to-dos (1). Frame 3: [2 items] arrives, 'Call Hana' is added. Frame 4: [3 items], 'Practise layouts' is added; every new value means one rebuild, with no FutureBuilder and no setState.](/_astro/flutter-future-and-stream-providers-stream.en.D0KvNX8w.gif)
![Animation in four frames. Left: a pipe labelled watchTodoList(): Stream<List<Todo>> and StreamProvider(initialData: const []); right: a phone titled 'Live to-dos'. Frame 1: the pipe is empty, the phone says 'No to-dos yet.', rebuilds so far: 0. Frame 2: a value [1 item] arrives, the phone shows 'Read chapter 8' highlighted, title Live to-dos (1). Frame 3: [2 items] arrives, 'Call Hana' is added. Frame 4: [3 items], 'Practise layouts' is added; every new value means one rebuild, with no FutureBuilder and no setState.](/_astro/flutter-future-and-stream-providers-stream.ckb.CdQsFobc.gif)
FutureBuilder, FutureProvider and StreamProvider side by sideFutureBuilder، FutureProvider و StreamProvider لە تەنیشت یەک
| If the data…ئەگەر دراوەکە… | Useبەکاری بهێنە |
|---|---|
| arrives once and only one screen needs itیەک جار دەگات و تەنها یەک شاشە پێویستی پێیەتی | FutureBuilder |
| arrives once and several screens need itیەک جار دەگات و چەند شاشەیەک پێویستیان پێیەتی | FutureProvider |
| keeps arriving (live) and several screens need itبەردەوام دەگات (زیندوو) و چەند شاشەیەک پێویستیان پێیەتی | StreamProvider |
| keeps arriving and one widget needs itبەردەوام دەگات و یەک پێویستی پێیەتی | StreamBuilder |
| is changed by the app itself (taps, forms)خودی دەیگۆڕێت (دەستلێدان، فۆڕم) | ChangeNotifierProvider |
Common mistakesهەڵە باوەکان
| Mistakeهەڵە | What happensچی ڕوو دەدات | Fixچاکردنەوە |
|---|---|---|
No initialDatainitialData نییە | Compile error in provider 5 and 6 compile لە provider 5 و 6ـدا | Give a starting value, or use a nullable type with nullنرخێکی سەرەتایی بدە، یان جۆرێکی nullable لەگەڵ null بەکار بهێنە |
Reading List<Todo> when the provider is List<Todo>?خوێندنەوەی List<Todo> لە کاتێکدا providerـەکە List<Todo>?ـە | ProviderNotFoundException | Watch the exact same typeڕێک هەمان جۆر watch بکە |
No catchError for a Future or Stream that can failcatchError نییە بۆ یان کە دەتوانێت شکست بهێنێت | The error is reported and the screen keeps initialData ڕادەگەیەنرێت و شاشەکە initialData دەهێڵێتەوە | Add catchError: (_, error) => …catchError: (_, error) => … زیاد بکە |
initialData: const [] when “loading” and “empty” must look differentinitialData: const [] کاتێک «بارکردن» و «بەتاڵ» دەبێت جیاواز دەربکەون | The user sees “No to-dos” while the data is still coming «هیچ ئەرکێک نییە» دەبینێت لە کاتێکدا دراوەکە هێشتا دێت | Use a nullable type and null for loadingجۆرێکی nullable و null بۆ بارکردن بەکار بهێنە |
| Using StreamProvider to change stateبەکارهێنانی StreamProvider بۆ گۆڕینی | Hard-to-follow code; the provider only shows valuesکۆدێکی قورس بۆ تێگەیشتن؛ providerـەکە تەنها نرخ پیشان دەدات | Change state in a ChangeNotifier لە ChangeNotifierـێکدا بگۆڕە |
Exercisesڕاهێنانەکان
This screen loads a quote of the day with a FutureBuilder. Rewrite it with a FutureProvider so that the screen becomes a StatelessWidget. Show a spinner while loading and “No quote today.” if loading fails.
ئەم شاشەیە وتەی ڕۆژ بە FutureBuilderـێک بار دەکات. بە FutureProviderـێک دووبارە بینووسەرەوە بۆ ئەوەی شاشەکە ببێت بە . لە کاتی بارکردندا بازنەیەکی چاوەڕوانی و ئەگەر بارکردن شکستی هێنا «No quote today.» پیشان بدە.
class QuoteScreenBefore extends StatefulWidget {
const QuoteScreenBefore({super.key});
@override
State<QuoteScreenBefore> createState() => _QuoteScreenBeforeState();
}
class _QuoteScreenBeforeState extends State<QuoteScreenBefore> {
late final Future<String> _quote = loadQuoteOfTheDay();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: FutureBuilder<String>(
future: _quote,
builder: (context, snapshot) {
if (!snapshot.hasData) return const CircularProgressIndicator();
return Text(snapshot.data!);
},
),
),
);
}
}Hintئاماژە
You need create, initialData, catchError and context.watch<String?>().
پێویستت بە create، initialData، catchError و context.watch<String?>() هەیە.
Show answerوەڵامەکە پیشان بدە
void main() {
runApp(
FutureProvider<String?>(
create: (_) => loadQuoteOfTheDay(),
initialData: null, // still loading
catchError: (_, _) => 'No quote today.',
child: const MaterialApp(home: QuoteScreen()),
),
);
}
class QuoteScreen extends StatelessWidget {
const QuoteScreen({super.key});
@override
Widget build(BuildContext context) {
final quote = context.watch<String?>();
return Scaffold(
body: Center(
child: quote == null
? const CircularProgressIndicator()
: Text(quote),
),
);
}
}String? with initialData: null separates loading from a real quote, and catchError turns a failure into a message. In a bigger app, wrap the text in a small class such as Quote: providers are found by type, and many things in an app are Strings.
String? لەگەڵ initialData: null بارکردن لە وتەیەکی ڕاستەقینە جیا دەکاتەوە و catchError شکستێک دەگۆڕێت بۆ پەیامێک. لە گەورەتردا، دەقەکە لە بچووکی وەک Quoteـدا بپێچە: providerـەکان بەپێی جۆر دەدۆزرێنەوە و زۆر شت لە Stringـن.
The slide's code FutureProvider<List<Todo>>(create: (_) => service.getTodoList(), child: const TodoListScreen()) does not compile. Why, and what is the smallest fix?
کۆدەکەی سلایدەکە FutureProvider<List<Todo>>(create: (_) => service.getTodoList(), child: const TodoListScreen()) compile نابێت. بۆچی و بچووکترین چاکردنەوە چییە؟
Show answerوەڵامەکە پیشان بدە
initialData is a required parameter in provider 5 and later, because the screen needs a List<Todo> before the Future completes. The smallest fix is initialData: const []; use FutureProvider<List<Todo>?> with initialData: null if loading must be visible.
initialData لە provider 5 و دواتردا پێویستە، چونکە شاشەکە پێش تەواوبوونی پێویستی بە List<Todo>ـێکە. بچووکترین چاکردنەوە initialData: const []ـە؛ ئەگەر بارکردن دەبێت دیار بێت، FutureProvider<List<Todo>?> لەگەڵ initialData: null بەکار بهێنە.
For each case, choose FutureBuilder, FutureProvider, StreamProvider or ChangeNotifierProvider: (a) a chat screen that shows new messages as they arrive from Firestore and an unread badge in the app bar; (b) the app's settings, loaded once at start, used on five screens; (c) a cart that the user changes with + and − buttons; (d) one screen that loads a single photo once.
بۆ هەر حاڵەتێک، FutureBuilder، FutureProvider، StreamProvider یان ChangeNotifierProvider هەڵبژێرە: (أ) شاشەیەکی چات کە نامە نوێیەکان لە کاتی گەیشتنیان لە Firestoreـەوە پیشان دەدات و نیشانەیەکی نەخوێندراوە لە ؛ (ب) ڕێکخستنەکانی ، کە یەک جار لە سەرەتادا بار دەکرێن و لە پێنج شاشەدا بەکار دێن؛ (ج) سەبەتەیەک کە بە + و − دەیگۆڕێت؛ (د) یەک شاشە کە یەک وێنە یەک جار بار دەکات.
Show answerوەڵامەکە پیشان بدە
- (a) StreamProvider: live values, needed in two places.
- (b) FutureProvider: one value, shared.
- (c) ChangeNotifierProvider: the app itself changes the data.
- (d) FutureBuilder: one value, one screen.
- (أ) StreamProvider: نرخی زیندوو، لە دوو شوێندا پێویستە.
- (ب) FutureProvider: یەک نرخ، هاوبەش.
- (ج) ChangeNotifierProvider: خودی دراوەکە دەگۆڕێت.
- (د) FutureBuilder: یەک نرخ، یەک شاشە.
Summaryپوختە
- Provider is also a tool for dependency injection: the lecture injects the signed-in User above MaterialApp with
Provider<User>.value. - FutureProvider creates a Future, waits for it and exposes the result; the screen just watches the value, with no State and no FutureBuilder.
- StreamProvider listens to a Stream and always exposes the latest value; every new value rebuilds the watchers.
initialDatais required for both (provider 5+). Use a nullable type withnullto show loading, andcatchErrorfor failures.- Choose by the data: one value for one screen →
FutureBuilder; shared →FutureProvider; live →StreamProvider; changed by the app →ChangeNotifierProvider.
- Provider ئامرازێکیشە بۆ : وانەکە چووە ژوورەوە بە
Provider<User>.valueلە سەرووی MaterialAppـەوە تێدەخات. - FutureProvider دروست دەکات، چاوەڕێی دەکات و ئەنجامەکەی دەدات؛ شاشەکە تەنها نرخەکە watch دەکات، بەبێ State و بەبێ FutureBuilder.
- StreamProvider گوێ لە دەگرێت و هەمیشە دوایین نرخ دەدات؛ هەر نرخێکی نوێ ئەوانەی watch دەکەن دووبارە دروست دەکاتەوە.
initialDataبۆ هەردووکیان پێویستە (provider 5+). جۆرێکی nullable لەگەڵnullبۆ پیشاندانی بارکردن وcatchErrorبۆ شکستەکان بەکار بهێنە.- بەپێی دراوەکە هەڵبژێرە: یەک نرخ بۆ یەک شاشە ←
FutureBuilder؛ هاوبەش ←FutureProvider؛ زیندوو ←StreamProvider؛ دەیگۆڕێت ←ChangeNotifierProvider.
Lesson complete!وانەکە تەواو بوو!
Well done. Review the key terms, then go on to the next lesson.دەستخۆش. سەیرێکی زاراوە سەرەکییەکان بکەرەوە، پاشان بڕۆ بۆ وانەی داهاتوو.
Key termsزاراوە سەرەکییەکان
ProxyProvider and ChangeNotifierProxyProviderProxyProvider و ChangeNotifierProxyProvider
Related lecturesوانە پەیوەندیدارەکان
- ChangeNotifier, ChangeNotifierProvider and MultiProviderChangeNotifier، ChangeNotifierProvider و MultiProvider
- Firebase and Cloud FirestoreFirebase و Cloud Firestore
- Synchronous and Asynchronous Workکاری هاوکات و ناهاوکات
- The Selector Widget: Fewer Rebuildsویجێتی Selector: دووبارە دروستکردنەوەی کەمتر
References and further readingسەرچاوەکان و خوێندنەوەی زیاتر
This lecture is a first edition. The Kurdish text and terminology are waiting for review by Kurdish IT teachers.ئەم وانەیە چاپی یەکەمە. دەقە کوردییەکە و زاراوەکانی چاوەڕێی پێداچوونەوەی مامۆستایانی کوردی بواری IT ن.