Provider: Theo dõi hay đọc
Thuộc phần Quản lý trạng thái trong hành trình Flutter của Coddy. Bài học 11 trên 27.
Có hai cách lấy một mô hình từ Provider, và mỗi cách thực hiện một việc khác nhau.
context.watch<StepCounter>() lấy mô hình và đăng ký theo dõi mô hình đó: khi mô hình gọi notifyListeners(), widget này sẽ dựng lại. Dùng cách này trong build cho mọi thứ hiển thị trên màn hình.
context.read<StepCounter>() lấy mô hình một lần mà không đăng ký theo dõi. Dùng cách này trong các hàm gọi lại như onPressed, khi bạn muốn gọi một phương thức chứ không muốn hiển thị gì:
Widget build(BuildContext context) {
final steps = context.watch<StepCounter>().steps; // hiển thị
return ElevatedButton(
onPressed: () => context.read<StepCounter>().walk(), // thực hiện thao tác
child: Text('$steps steps'),
);
}Nhầm lẫn hai cách này là bạn sẽ thấy ngay. Dùng read trong build khiến giá trị đầu tiên hiển thị mãi. Dùng watch bên trong onPressed sẽ gây lỗi, vì thao tác chạm không phải là quá trình dựng giao diện và không có gì để đăng ký theo dõi.
Thử thách
DễWalk cộng thêm 1000 bước vào model, nhưng màn hình vẫn hiển thị 0 steps.
- Để dòng hiển thị số bước cập nhật theo model, mỗi lần chạm sẽ hiện số mới.
- Giữ nguyên lời gọi của nút.
Tự làm thử
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class StepCounter extends ChangeNotifier {
int _steps = 0;
int get steps => _steps;
void walk() {
_steps += 1000;
notifyListeners();
}
}
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => StepCounter(),
child: const MyApp(),
),
);
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
final steps = context.read<StepCounter>().steps;
return Scaffold(
appBar: AppBar(title: const Text('Steps')),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text('$steps steps', style: const TextStyle(fontSize: 40)),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () {
context.read<StepCounter>().walk();
},
child: const Text('Walk'),
),
],
),
),
);
}
}
Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Quản lý trạng thái
Tự luyện tập: Trình biên dịch Flutter online