Flutter数据获取状态管理插件fetching_state的使用
Flutter数据获取状态管理插件fetching_state的使用
fetching_state
是一个小型的 Flutter 插件,帮助你轻松地处理基于远程数据获取状态的 UI 变化。本文将详细介绍如何安装、使用 fetching_state
插件,并提供一个完整的示例。
目录
特点
- 减少 UI 中的
if else
语句:使 UI 代码更简洁。 - 在四种状态下决定显示内容:
[init, loading, done, error, loadingMore]
。 - 可传递数据或错误对象:在
onDone
和onError
中使用。
入门指南
安装库
在你的 pubspec.yaml
文件中添加依赖:
dependencies:
fetching_state:
然后在需要使用的地方导入库:
import 'package:fetching_state/fetching_state.dart';
使用方法
1. FetchingState
示例代码
import 'package:flutter/material.dart';
import 'package:fetching_state/fetching_state.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fetching State FetchingStateExample',
theme: ThemeData(
primarySwatch: Colors.blue,
textTheme: const TextTheme(
bodyText2: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
home: const FetchingStateExample(),
);
}
}
class FetchingStateExample extends StatefulWidget {
const FetchingStateExample({Key? key}) : super(key: key);
@override
_FetchingStateExampleState createState() => _FetchingStateExampleState();
}
class _FetchingStateExampleState extends State<FetchingStateExample> {
late FetchingState<String?> _fetching;
@override
void initState() {
_fetching = FetchingState.init(data: null);
super.initState();
}
Future<void> getDone() async {
setState(() {
_fetching = _fetching.copyWhenLoading();
});
await Future.delayed(const Duration(milliseconds: 500));
setState(() {
_fetching = _fetching.copyWhenDone(data: 'DONE IN STATE');
});
}
Future<void> loadMoreText() async {
setState(() {
_fetching = _fetching.copyWhenLoadingMore();
});
await Future.delayed(const Duration(milliseconds: 500));
if (_fetching.data == null) {
setState(() {
_fetching = _fetching.copyWhenError(error: 'No current data');
});
return;
}
setState(() {
_fetching = _fetching.copyWhenDone(data: '${_fetching.data} - extra text');
});
}
Future<void> getError() async {
setState(() {
_fetching = _fetching.copyWhenLoadingMore();
});
await Future.delayed(const Duration(milliseconds: 500));
setState(() {
_fetching = _fetching.copyWhenError(error: 'Error IN STATE');
});
}
Future<void> getInit() async {
setState(() {
_fetching = _fetching.copyWhenLoadingMore();
});
await Future.delayed(const Duration(milliseconds: 500));
setState(() {
_fetching = FetchingState.init(data: '');
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Spacer(),
Center(
child: Builder(
builder: (context) {
return _fetching.when(
onInit: () => const Text(
'INIT',
style: TextStyle(color: Colors.blue),
),
onDone: (text, isLoadingMore) => Text(
'${text ?? ''} ${isLoadingMore ? '....' : ''}',
style: const TextStyle(color: Colors.green),
),
onError: (error) => Text(
error!.toString(),
style: const TextStyle(color: Colors.red),
),
onLoading: () => const CircularProgressIndicator(),
);
},
),
),
const SizedBox(
height: 40,
),
ElevatedButton(
onPressed: getDone,
child: const Text('Done'),
),
ElevatedButton(
onPressed: loadMoreText,
child: const Text('Load more text'),
),
ElevatedButton(
onPressed: getError,
child: const Text('Error'),
),
ElevatedButton(
onPressed: getInit,
child: const Text('Init'),
),
const Spacer(),
SizedBox(
width: MediaQuery.of(context).size.width * .8,
height: 60,
child: TextButton(
style: TextButton.styleFrom(
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
),
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => const LoadStatusExample()),
);
},
child: const Text('Load Status'),
),
),
],
),
),
);
}
}
2. LoadStatus
示例代码
class Counter with LoadStatusMixin {
final int value;
Counter(this.value);
Counter copyWith({int? value}) {
return Counter(value ?? this.value);
}
}
class LoadStatusExample extends StatefulWidget {
const LoadStatusExample({Key? key}) : super(key: key);
@override
State<LoadStatusExample> createState() => _LoadStatusExampleState();
}
class _LoadStatusExampleState extends State<LoadStatusExample> {
Counter _counter = Counter(1);
void increase() async {
setState(() {
_counter.setLoadStatusLoading();
});
await Future.delayed(const Duration(milliseconds: 500));
setState(() {
_counter = _counter.copyWith(value: _counter.value + 1);
_counter.setLoadStatusDone();
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Load Status Example'),
),
body: Center(
child: Column(
children: [
const Spacer(),
Builder(
builder: (context) {
return _counter.whenOrElse(
onLoading: () => const CircularProgressIndicator(),
onDone: (_) => Text(_counter.value.toString()),
onInit: () => const Text('Init'),
onError: () => const Text('Error'),
orElse: () => const Text('Nothing'),
);
},
),
const SizedBox(height: 10),
ElevatedButton(
onPressed: increase,
child: const Text('Add'),
),
const Spacer(),
],
),
),
);
}
}
3. LoadingState
LoadingState
类似于 FetchingState
,但不需要数据对象。适用于只需要简单状态的情况。
欢迎反馈
如果你发现任何需要改进的地方或有新的功能需求,请在 GitHub 上创建一个 issue。
希望本文对你有所帮助!如果有任何问题,欢迎随时提问。
更多关于Flutter数据获取状态管理插件fetching_state的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter数据获取状态管理插件fetching_state的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,fetching_state
是一个用于 Flutter 的状态管理库,它主要用于处理数据获取过程中的状态管理,如加载中、加载成功、加载失败等。以下是如何在 Flutter 应用中使用 fetching_state
的一个简单示例。
首先,确保你已经在 pubspec.yaml
文件中添加了 fetching_state
依赖:
dependencies:
flutter:
sdk: flutter
fetching_state: ^最新版本号 # 请替换为实际的最新版本号
然后运行 flutter pub get
来安装依赖。
接下来,我们来看一个具体的代码示例:
1. 创建一个数据模型
假设我们要获取一个用户列表,首先创建一个用户数据模型:
class User {
final String name;
final int age;
User({required this.name, required this.age});
factory User.fromJson(Map<String, dynamic> json) {
return User(
name: json['name'] as String,
age: json['age'] as int,
);
}
}
2. 创建 FetchingState 提供者和数据获取逻辑
使用 fetching_state
来管理数据获取状态:
import 'package:flutter/material.dart';
import 'package:fetching_state/fetching_state.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
class UserFetching extends FetchingState<List<User>, Exception> {
@override
Future<List<User>> fetchData() async {
final response = await http.get(Uri.parse('https://api.example.com/users'));
if (response.statusCode == 200) {
final List<dynamic> body = jsonDecode(response.body);
return body.map((dynamic item) => User.fromJson(item)).toList();
} else {
throw Exception('Failed to load users');
}
}
}
3. 使用 FetchingState 提供者在 UI 中显示数据
在你的 Flutter 应用中使用 UserFetching
提供者来显示用户列表:
void main() {
runApp(
FetchingProvider<List<User>, Exception>(
create: () => UserFetching(),
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: UserListScreen(),
);
}
}
class UserListScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
final fetchingState = FetchingState.of<List<User>, Exception>(context);
return Scaffold(
appBar: AppBar(
title: Text('User List'),
),
body: fetchingState.when(
data: (users) {
return ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) {
final user = users[index];
return ListTile(
title: Text(user.name),
subtitle: Text('Age: ${user.age}'),
);
},
);
},
loading: () => Center(child: CircularProgressIndicator()),
error: (e, retry) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Failed to load users'),
TextButton(
onPressed: () => retry(),
child: Text('Retry'),
),
],
),
);
},
),
);
}
}
解释
- 数据模型:
User
类用于表示用户数据。 - FetchingState 提供者:
UserFetching
类扩展了FetchingState
并实现了fetchData
方法,用于从 API 获取用户数据。 - UI 显示:
UserListScreen
使用FetchingProvider
包裹,并在build
方法中使用FetchingState.of
获取fetchingState
。然后,根据fetchingState
的状态(加载中、数据、错误),显示相应的 UI。
这样,你就可以在 Flutter 应用中使用 fetching_state
来管理数据获取的状态了。