Nghệ thuật Flutter : Quản lý State với Redux
Quản lý state với Redux là một cách rất phổ biến đối với các ứng dụng viết bằng JavaScript và trong Flutter nó cũng được sử dụng.
Redux là gì ?
“Redux is a predictable state container for JavaScript apps”
Redux giống như một công cụ để quản lý trạng thái ( State management ).
Nó giúp ứng dụng hoạt động một cách nhất quán, chạy trong các môi trường khác nhau(client, server, native) dễ dàng để test, debug.
Nhìn sơ qua thì có thể thấy, cách quản lý state này cũng khá giống với InheritedWidget hoặc Provider đúng không ? Vậy chúng ta cùng đi chi tiết nhé 🙂
Cấu tạo và nguyên lý làm việc của Redux
Redux có 3 phần chính:
1. Store
Là một đối tượng, có nhiều cặp khoá ( key-value) đại diện cho trạng thái hiện tại của ứng dụng.
Store cung cấp trạng thái ứng dụng, mỗi khi trạng thái cập nhật, view được tải lại.
2. Action
Là một đối tượng, gửi thông tin từ ứng dụng lên Store và là nguồn thông tin duy nhất lên Store
3.Reducer
Một action mô tả vấn đề, reducer chịu trách nhiệm giải quyết vấn đề.
Ví dụ
Tạo một project mới
Khai báo thư viện:
1 |
flutter_redux: 0.7.0 |
Trong file main.dart:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:redux/redux.dart'; // Tạo một Action : Tăng enum Actions { Increment } // The reducer : Khi nhận được Action: Increment, thì biến số state sẽ thay đổi- tăng lên 1 int counterReducer(int state, dynamic action) { if (action == Actions.Increment) { return state + 1; } return state; } void main() { // Khởi tạo một Store có State ban đầu là 0, counterReducer thì State cũng thay đổi final store = new Store<int>(counterReducer, initialState: 0); runApp(new FlutterReduxApp( title: 'Flutter Redux Demo', store: store, )); } class FlutterReduxApp extends StatelessWidget { final Store<int> store; final String title; FlutterReduxApp({Key key, this.store, this.title}) : super(key: key); @override Widget build(BuildContext context) { // Kết nối Store với App thông qua StoreProvider return new StoreProvider<int>( store: store, child: new MaterialApp( theme: new ThemeData.dark(), title: title, home: new Scaffold( appBar: new AppBar( title: new Text(title), ), body: new Center( child: new Column( mainAxisAlignment: MainAxisAlignment.center, children: [ new Text( 'You have pushed the button this many times:', ), // StoreConnector - là một interface với App để hiển thị hoặc tương tác new StoreConnector<int, String>( converter: (store) => store.state.toString(), builder: (context, count) { return new Text( count, style: Theme.of(context).textTheme.display1, ); }, ) ], ), ), // StoreConnector - là một interface với App để tương tác floatingActionButton: new StoreConnector<int, VoidCallback>( converter: (store) { return () => store.dispatch(Actions.Increment); }, builder: (context, callback) { return new FloatingActionButton( onPressed: callback, tooltip: 'Increment', child: new Icon(Icons.add), ); }, ), ), ), ); } } |
Kết quả:
Giải thích:
Các bước để thực hiện :
– Tạo Action
1 2 |
// Tạo một Action : Tăng enum Actions { Increment } |
– Tạo hàm Reducer
1 2 3 4 5 6 7 8 |
// The reducer : Khi nhận được Action: Increment, thì biến số state sẽ thay đổi- tăng lên 1 int counterReducer(int state, dynamic action) { if (action == Actions.Increment) { return state + 1; } return state; } |
– Khởi tạo Store để giao tiếp với App
1 2 |
// Khởi tạo một Store có State ban đầu là 0, counterReducer thì State cũng thay đổi final store = new Store<int>(counterReducer, initialState: 0); |
– Liên kết Store với App
+ Dùng StoreProvider để liên kết App với Store đã khai báo bên trên
1 2 3 |
new StoreProvider<int>( store: store, child: new MaterialApp(.... |
+ Dùng StoreConnector để hỗ trợ hiển thị khi nhận được Action và hiển thị.
1 2 3 4 5 6 7 8 9 |
StoreConnector<int, String>( converter: (store) => store.state.toString(), builder: (context, count) { return new Text( count, style: Theme.of(context).textTheme.display1, ); }, ) |
+ Dùng để tương tác với Action
1 2 3 4 5 6 7 8 9 10 11 12 |
new StoreConnector<int, VoidCallback>( converter: (store) { return () => store.dispatch(Actions.Increment); }, builder: (context, callback) { return new FloatingActionButton( onPressed: callback, tooltip: 'Increment', child: new Icon(Icons.add), ); }, ), |
Qua ví dụ đơn giản trên các bạn có thể hiểu căn bản về Redux trong Flutter. Hy vọng bạn có nhiều kiến thức từ team Báo Flutter.