Hai màn hình, một mô hình
Thuộc phần Quản lý trạng thái trong hành trình Flutter của Coddy. Bài học 13 trên 27.
Dữ liệu được hai màn hình chia sẻ chính là lúc Provider phát huy tác dụng. Màn hình Settings thay đổi tên, còn màn hình chính hiển thị tên đó, mà hai màn hình không cần truyền dữ liệu cho nhau.
Vị trí đặt provider rất quan trọng. MaterialApp chứa một Navigator, và mỗi màn hình bạn mở sẽ được thêm vào đó bên cạnh home, chứ không nằm bên trong:
ChangeNotifierProvider <- above MaterialApp: every screen finds it
MaterialApp
Navigator
HomePage
SettingsScreen <- pushed next to HomePageProvider bọc quanh HomePage chỉ tiếp cận được HomePage. Màn hình được mở không nằm bên dưới nó, nên không thể tìm thấy model. Đặt provider phía trên MaterialApp, trong main, để mọi màn hình cùng chia sẻ model đó.
Đừng sửa lỗi bằng cách thêm một ChangeNotifierProvider thứ hai ở màn hình còn lại. Cách đó tạo ra model thứ hai: lỗi biến mất, nhưng các màn hình không còn chia sẻ dữ liệu.
Thử thách
Trung bìnhNhấn vào biểu tượng bánh răng, nhập tên rồi nhấn Save: ứng dụng báo lỗi vì provider chỉ bọc HomePage.
- Chuyển
ChangeNotifierProviderra khỏiMyAppvà đưa vàomain, bao quanhMyApp.
Sau đó, lưu Ada sẽ hiển thị Hello, Ada! ở trang chủ.
Tự làm thử
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class Profile extends ChangeNotifier {
String _name = 'Guest';
String get name => _name;
void rename(String newName) {
_name = newName;
notifyListeners();
}
}
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: ChangeNotifierProvider(
create: (context) => Profile(),
child: const HomePage(),
),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
final profile = context.watch<Profile>();
return Scaffold(
appBar: AppBar(
title: const Text('Home'),
actions: [
IconButton(
icon: const Icon(Icons.settings),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const SettingsScreen()),
);
},
),
],
),
body: Center(
child: Text('Hello, ${profile.name}!', style: const TextStyle(fontSize: 32)),
),
);
}
}
class SettingsScreen extends StatefulWidget {
const SettingsScreen({super.key});
@override
State<SettingsScreen> createState() => _SettingsScreenState();
}
class _SettingsScreenState extends State<SettingsScreen> {
final controller = TextEditingController();
@override
Widget build(BuildContext context) {
final profile = context.watch<Profile>();
return Scaffold(
appBar: AppBar(title: const Text('Settings')),
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
Text('Signed in as ${profile.name}'),
const SizedBox(height: 16),
TextField(
controller: controller,
decoration: const InputDecoration(labelText: 'Your name'),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () {
context.read<Profile>().rename(controller.text);
Navigator.pop(context);
},
child: const Text('Save'),
),
],
),
),
);
}
}
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