Provider: Consumer
Thuộc phần Quản lý trạng thái trong hành trình Flutter của Coddy. Bài học 12 trên 27.
Ở đây, provider được tạo bên trong build của chính MyApp, và build đó yêu cầu đèn ngay bên dưới. Ứng dụng hiển thị lỗi: context thuộc về MyApp, nằm phía trên provider, còn một widget chỉ có thể tìm thấy các provider nằm phía trên nó.
Consumer khắc phục điều đó. Đây là một widget, nên nó nằm bên dưới provider, còn builder của nó nhận được một context mới và chính model đó:
Consumer<Lamp>(
builder: (context, lamp, child) {
return Text(lamp.isOn ? 'On' : 'Off');
},
)Builder chạy lại mỗi khi đèn gọi notifyListeners(), giống như một widget theo dõi đèn. Bên trong đó, bạn có thể gọi trực tiếp các phương thức của model trên lamp: onPressed: () => lamp.toggle().
Consumer cũng chỉ dựng lại phần mà nó bao bọc, vì vậy bao bọc phần thay đổi sẽ giữ nguyên các phần còn lại trên màn hình. Trong hầu hết ứng dụng, bạn sẽ dùng context.watch trong một widget riêng, và dùng Consumer khi cùng ở trong build với provider.
Thử thách
Trung bìnhỨng dụng mở ra và báo lỗi. Đặt các phần của đèn bên trong một Consumer:
- Bọc
Columntrong mộtConsumer<Lamp>và trả vềColumntừ hàm dựng của nó. - Bên trong, dùng
lamptừ hàm dựng cho biểu tượng, văn bản và nút.
Tự làm thử
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class Lamp extends ChangeNotifier {
bool _isOn = false;
bool get isOn => _isOn;
void toggle() {
_isOn = !_isOn;
notifyListeners();
}
}
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => Lamp(),
child: MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(title: const Text('Lamp')),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
context.watch<Lamp>().isOn ? Icons.lightbulb : Icons.lightbulb_outline,
size: 96,
color: context.watch<Lamp>().isOn ? Colors.amber : Colors.grey,
),
Text(context.watch<Lamp>().isOn ? 'The lamp is on' : 'The lamp is off'),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () => context.read<Lamp>().toggle(),
child: const Text('Switch'),
),
],
),
),
),
),
);
}
}
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