Quản lý trạng thái và Chèn phụ thuộc trong Flutter
- 10-06-2024
- Toanngo92
- 0 Comments
Mục lục
Quản lý Trạng thái trong Flutter
Quản lý trạng thái là khái niệm quan trọng nhất trong Phát triển Ứng dụng Flutter. Quản lý trạng thái có nghĩa là quản lý dữ liệu của ứng dụng trong thời gian chạy.
Trong Flutter, có hai loại widget là Stateful và Stateless. Đối với Stateful widget, dữ liệu có thể thay đổi trong thời gian chạy bằng cách quản lý các trạng thái. Đối với Stateless widget, trạng thái của widget sau khi được xây dựng không thể thay đổi. Vì vậy, không có quản lý trạng thái cho Stateless widget.
Dưới đây là một ví dụ để hiểu khái niệm quản lý trạng thái:
Giả sử rằng một ứng dụng bán hàng đang được xây dựng. Trên trang sản phẩm, người dùng có thể nhấp vào nút “Thêm vào giỏ hàng” và sử dụng biểu tượng “thêm” hoặc “bớt” để tăng hoặc giảm số lượng của bất kỳ mặt hàng nào tương ứng. Quản lý trạng thái giúp thực hiện việc tăng và giảm này. Hơn nữa, trong ví dụ được thảo luận, điều quan trọng là phải duy trì dữ liệu giỏ hàng trong suốt quá trình mua hàng hoặc duyệt và điều này cũng đạt được với sự trợ giúp của quản lý trạng thái. Thông tin được sử dụng để thêm danh sách các mặt hàng vào giỏ hàng được lưu trữ trong một lớp riêng. Lớp này được sử dụng để theo dõi tất cả các hoạt động.
Các loại Quản lý Trạng thái trong Flutter
Dựa trên tính khả dụng, quản lý trạng thái được phân loại thành hai loại:
Quản lý Trạng thái Tạm thời
Trong quản lý trạng thái tạm thời, việc quản lý trạng thái chỉ kéo dài trong vài giây. Ví dụ, khi người dùng nhấp vào “Thêm vào giỏ hàng”, kiểu nút có thể thay đổi thành các nút “thêm” và “bớt” với số lượng mặt hàng hiển thị ở bên cạnh. Quản lý trạng thái này, nơi thay đổi từ “Thêm vào giỏ hàng” thành “thêm” và “bớt” chỉ diễn ra trong vài giây là một ví dụ tốt để minh họa Quản lý Trạng thái Tạm thời.
Stateful Widget là một ví dụ khác của loại Quản lý Trạng thái này. Trong stateful widget, trạng thái hiện tại của widget được biết và nếu có bất kỳ thay đổi nào cần thực hiện đối với trạng thái, giá trị sẽ được thay đổi. Việc thay đổi này chỉ mất một phần nhỏ của giây và dễ dàng thực hiện.
App State
Trong quản lý trạng thái ứng dụng, việc quản lý trạng thái kéo dài suốt thời gian của ứng dụng hoặc trong phạm vi của ứng dụng. Ví dụ, dữ liệu trong giỏ hàng phải được duy trì trong suốt ứng dụng bất kể trang nào người dùng vào. Có nhiều cách để đạt được điều này, nhưng scoped_model là cách tốt nhất để triển khai và theo dõi App State vì nó dễ dàng và nhanh chóng sử dụng. App state bao gồm ba lớp chính.
Dưới đây là các lớp chính cho App State:
- Models: Có thể sử dụng để mở rộng lớp Model để lắng nghe các thay đổi.
- ScopedModel: Được sử dụng để bao bọc các thành phần UI và truy cập dữ liệu từ Model.
- ScopedModelDescendant: Được sử dụng để xác định ScopedModel đúng từ hệ thống widget.
Chèn phụ thuộc trong Flutter
Chèn phụ thuộc trong Flutter là một cơ chế mà qua đó một đối tượng cung cấp phụ thuộc cho đối tượng khác. Nói đơn giản hơn, đó là một kỹ thuật lập trình giúp lớp trở nên độc lập với các phụ thuộc của nó. Hơn nữa, chèn phụ thuộc cho phép tạo các đối tượng phụ thuộc bên ngoài lớp và cung cấp những đối tượng đó cho lớp theo nhiều cách. Nó cũng giúp giảm bớt việc tạo và ràng buộc các đối tượng phụ thuộc từ các lớp. Cuối cùng, chèn phụ thuộc cung cấp kiểm tra dễ dàng hơn, mức độ linh hoạt cao hơn và sự cô lập.
Tạo Ứng dụng với Chèn phụ thuộc trong Flutter
Tiêm phụ thuộc trong ứng dụng có thể được thực hiện theo hai cách:
- Inherited Widget
- Provider Package
Chèn phụ thuộc sử dụng Inherited Widget
Chèn phụ thuộc sử dụng InheritedWidget
cho phép dữ liệu truyền xuống cây widget dễ dàng. Điều này có nghĩa là dữ liệu có thể được chuyển dễ dàng từ widget cha đến widget con.
Trong 2 đoạn mã bên dưới, lớp InheritedWidget
được sử dụng để tạo một widget và Text.
Đoạn mã 1:
import 'package:flutter/material.dart';
import 'InheritedWidget.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return InheritedHomeWidget(
title: 'Dependency Injection Text',
key: key,
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Demo'),
),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(InheritedHomeWidget.of(context).title),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: const <Widget>[
Text("Dependency Injection Demo"),
],
),
);
}
}
Đoạn mã 2:
import 'package:flutter/material.dart';
class InheritedHomeWidget extends InheritedWidget {
const InheritedHomeWidget({
Key? key,
required this.title,
required Widget child,
}) : super(key: key, child: child);
final String title;
static InheritedHomeWidget of(BuildContext context) {
final InheritedHomeWidget? result =
context.dependOnInheritedWidgetOfExactType<InheritedHomeWidget>();
assert(result != null, 'No InheritedHomeWidget found in context');
return result!;
}
@override
bool updateShouldNotify(InheritedHomeWidget oldWidget) {
return title != oldWidget.title;
}
}
Trong ví dụ này, một lớp InheritedWidget
được gọi là InheritedHomeWidget
được tạo ra, được sử dụng trong widget HomePage
. Ở đây, dữ liệu từ widget kế thừa có sẵn cho HomeWidget
. Hình bên dưới mô tả đầu ra.
Dependency Injection Sử Dụng Gói Provider trong Flutter
Đối với việc sử dụng dependency injection bằng gói provider, người dùng phải thêm gói provider vào dự án Flutter. Thêm provider: ^6.0.4
trong phần dependencies của file pubspec.yaml
và sau đó chạy flutter pub get
để thêm gói Provider vào dự án Flutter. Sau đó, gói này phải được import vào các tệp nơi nó sẽ được sử dụng.
Trong 2 Đoạn mã dưới đây, một đoạn văn được thêm vào trong provider và sau đó, provider sẽ được thêm vào trong hàm main. Một điều khác để quan sát là làm thế nào có thể truy cập đoạn văn bất kỳ lúc nào trong ứng dụng.
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:works/api.dart.dart';
void main() {
Provider.debugCheckInvalidvalueType = null;
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [Provider.value(value: Api())],
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Demo'),
),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
Provider.value(value: Api()),
ProxyProvider<Api, HomeModel>(
update: (context, api, homeModel) => HomeModel(api: api),
),
import 'package:flutter/cupertino.dart';
class Api {
String get loggedIn => 'I am logged in';
}
class HomeModel extends ChangeNotifier {
final Api api;
HomeModel({required this.api});
}
Trong ví dụ này, Api.dart được bổ sung bằng cách sử dụng một provider. Provider này là một kỹ thuật quản lý trạng thái và nhờ vào điều này, main.dart có thể truy cập vào chuỗi có tên là loggedIn. Tóm lại, nhờ vào việc tiêm phụ thuộc, dữ liệu trong Api.dart có thể được truy cập ở bất kỳ đâu trong ứng dụng với sự trợ giúp của Provider. Hình bên dưới miêu tả kết quả.