Hướng dẫn sử dụng Flutter Provider chi tiết
Provider là một thư viện phổ biến trong Flutter giúp quản lý trạng thái (state management) một cách hiệu quả. Dưới đây là hướng dẫn sử dụng Provider cơ bản và nâng cao.
1. Cài đặt Provider
Thêm thư viện vào dự án bằng cách sửa file pubspec.yaml
:
dependencies:
provider: ^6.0.5
YAMLSau đó chạy lệnh:
flutter pub get
Bash2. Nguyên lý hoạt động
Provider hoạt động dựa trên việc cung cấp (provide) dữ liệu từ cha đến con trong cây widget thông qua context. Dữ liệu này có thể được lắng nghe và cập nhật theo thời gian thực.
3. Các bước cơ bản sử dụng Provider
Bước 1: Tạo Model
Tạo một class để lưu trữ và quản lý trạng thái.
Ví dụ: Quản lý trạng thái bộ đếm.
import 'package:flutter/foundation.dart';
class CounterModel with ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners(); // Thông báo thay đổi dữ liệu
}
void decrement() {
if (_count > 0) {
_count--;
notifyListeners();
}
}
}
DartBước 2: Cung cấp Provider
Sử dụng ChangeNotifierProvider
để cung cấp dữ liệu cho toàn bộ ứng dụng hoặc một phần widget tree.
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'counter_model.dart'; // Import CounterModel
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => CounterModel()), // Khởi tạo CounterModel
],
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: CounterScreen(),
);
}
}
DartBước 3: Sử dụng dữ liệu từ Provider
Dùng Consumer
hoặc Provider.of
để truy cập và cập nhật dữ liệu.
class CounterScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Provider Example')),
body: Center(
child: Consumer<CounterModel>(
builder: (context, counter, child) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Count: ${counter.count}', style: TextStyle(fontSize: 24)),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
icon: Icon(Icons.remove),
onPressed: counter.decrement,
),
IconButton(
icon: Icon(Icons.add),
onPressed: counter.increment,
),
],
),
],
);
},
),
),
);
}
}
Dart4. Sử dụng Provider.of
Ngoài Consumer
, bạn có thể dùng Provider.of
để truy cập dữ liệu:
@override
Widget build(BuildContext context) {
final counter = Provider.of<CounterModel>(context);
return Scaffold(
appBar: AppBar(title: Text('Provider Example')),
body: Center(
child: Text('Count: ${counter.count}', style: TextStyle(fontSize: 24)),
),
floatingActionButton: FloatingActionButton(
onPressed: counter.increment,
child: Icon(Icons.add),
),
);
}
Dart5. Nâng cao: Sử dụng Selector
Selector
chỉ rebuild widget khi dữ liệu cụ thể thay đổi, giúp tối ưu hiệu suất.
class CounterScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Selector<CounterModel, int>(
selector: (_, counter) => counter.count,
builder: (_, count, __) {
return Text('Count: $count', style: TextStyle(fontSize: 24));
},
),
),
);
}
}
Dart6. MultiProvider
Khi ứng dụng có nhiều trạng thái, bạn có thể sử dụng MultiProvider
:
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => CounterModel()),
ChangeNotifierProvider(create: (_) => AnotherModel()),
],
child: MyApp(),
),
);
}
Dart7. Best Practices
- Tổ chức code:
- Tách biệt logic (model) và UI (widget).
- Sử dụng thư mục rõ ràng:
models
,providers
,screens
.
- Tránh lạm dụng
Provider.of
trong build:- Nên dùng
Consumer
hoặcSelector
để giảm việc rebuild không cần thiết.
- Nên dùng
- Chỉ dùng
notifyListeners()
khi thực sự cần thiết:- Điều này giúp tránh render lại toàn bộ widget tree.
8. Kết luận
Provider là giải pháp state management dễ học và hiệu quả trong Flutter. Bạn có thể mở rộng với các pattern phức tạp hơn như MVVM hoặc Clean Architecture để tổ chức code tốt hơn.