Hướng dẫn sử dụng Flutter Provider chi tiết

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
YAML

Sau đó chạy lệnh:

flutter pub get
Bash

2. 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();
    }
  }
}
Dart

Bướ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(),
    );
  }
}
Dart

Bướ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,
                    ),
                  ],
                ),
              ],
            );
          },
        ),
      ),
    );
  }
}
Dart

4. 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),
    ),
  );
}
Dart

5. 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));
          },
        ),
      ),
    );
  }
}
Dart

6. 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(),
    ),
  );
}
Dart

7. Best Practices

  1. 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.
  2. Tránh lạm dụng Provider.of trong build:
    • Nên dùng Consumer hoặc Selector để giảm việc rebuild không cần thiết.
  3. 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.

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *