Flutter数据查询插件query_client的使用
Flutter数据查询插件query_client的使用
query_client
是一个类似 React Hook 的工具,专门为 Flutter 设计。它可以帮助开发者轻松处理 API 请求、自动更新 UI、实现无限加载(分页加载)以及本地数据的即时变更。
特性
1. 简单的API请求
query_client
提供了简单的 API 请求方式,只需传入一个异步函数即可完成数据获取。
// 定义 QueryClient
final _queryClient = QueryClient<bool>(
({data, dataList}) async {
// 模拟延迟
await Future.delayed(Duration(seconds: 1));
return true;
},
);
// 在 Widget 中使用 FutureBuilder
Widget build() {
return FutureBuilder(
future: _queryClient.future, // 使用 QueryClient 的 future 属性
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return Text("just work");
}
return Text("Loading...");
},
);
}
2. 自动更新UI
通过 onUpdate
回调,可以实现在数据变化时自动更新 UI。
final _queryClient = QueryClient<bool>(
({data, dataList}) async {
await Future.delayed(Duration(seconds: 1));
return true;
},
onUpdate: () {
// 如果需要自动更新 UI,可以调用 setState
if (mounted) setState(() {});
},
);
Widget build() {
if (_queryClient.isLoading) {
return Center(child: Text("Loading..."));
}
if (_queryClient.isError) {
print("[MyWidget] error ${_queryClient.error}");
return GestureDetector(
child: Center(child: Text("🤕 Something went wrong! Tap to retry")),
onTap: () {
// 重试请求
_queryClient.request();
},
);
}
return Center(child: Text("🎉 It works! ${_queryClient.data}"));
}
3. 无限加载(分页模式)
query_client
支持无限加载功能,可以通过 loadMore()
方法加载更多数据。
final _queryClient = QueryClient<bool>(
({data, dataList}) async {
if (data != null) {
// 使用上一次的数据来加载下一页
await Future.delayed(Duration(seconds: 1));
} else {
await Future.delayed(Duration(seconds: 1));
}
return true;
},
onUpdate: () {
if (mounted) setState(() {});
},
);
Widget build() {
if (_queryClient.isLoading) {
return Center(child: Text("Loading..."));
}
if (_queryClient.isError) {
print("[MyWidget] error ${_queryClient.error}");
return GestureDetector(
child: Center(child: Text("🤕 Something went wrong! Tap to retry")),
onTap: () {
// 重试请求
_queryClient.request();
},
);
}
return GestureDetector(
child: Center(
child: Text("🎉 It works! ${_queryClient.data}. Tap to load more."),
),
onTap: () {
// 加载更多数据
_queryClient.loadMore();
},
);
}
4. 数据变更(Mutate Data)
当需要对已加载的数据进行变更(如删除一条记录),可以使用 mutate()
方法。
final _queryClient = QueryClient<bool>(
({data, dataList}) async {
if (data != null) {
// 使用上一次的数据来加载下一页
await Future.delayed(Duration(seconds: 1));
} else {
await Future.delayed(Duration(seconds: 1));
}
return true;
},
onUpdate: () {
if (mounted) setState(() {});
},
);
Widget build() {
if (_queryClient.isLoading) {
return Center(child: Text("Loading..."));
}
if (_queryClient.isError) {
print("[MyWidget] error ${_queryClient.error}");
return GestureDetector(
child: Center(child: Text("🤕 Something went wrong! Tap to retry")),
onTap: () {
// 重试请求
_queryClient.request();
},
);
}
final list = data.list;
return GestureDetector(
child: Column(
children: list.map((x) {
return GestureDetector(
child: Text(x.name),
onTap: () {
// 删除该项
_queryClient.mutate(({data, dataList}) {
// 从列表中移除该数据
final originIndex = data.list.indexWhere((y) => y.id == x.id);
final origin = data.list.removeAt(originIndex);
// 发送删除请求到服务器
return Request.deleteItem(x.id)
.then((res) {
// 成功则无需操作
})
.catchError((err) {
// 失败则将数据放回原位置
data.list.insert(originIndex, origin);
// 提示用户
Toast.show("🤕 Something went wrong! Try again!");
});
});
},
);
}).toList(),
),
onTap: () {
// 加载更多数据
_queryClient.loadMore();
},
);
}
更多关于Flutter数据查询插件query_client的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
query_client
是一个用于在 Flutter 应用中简化数据查询和状态管理的插件。它通常用于与后端 API 进行交互,并管理查询的状态(如加载、成功、错误等)。query_client
的设计灵感来自于 React Query,它提供了一种简单且强大的方式来管理异步数据。
安装 query_client
首先,你需要在 pubspec.yaml
文件中添加 query_client
依赖:
dependencies:
flutter:
sdk: flutter
query_client: ^0.1.0 # 请使用最新版本
然后运行 flutter pub get
来安装依赖。
基本用法
1. 创建 QueryClient
QueryClient
是 query_client
的核心类,它负责管理所有的查询。你可以在应用的顶层创建一个 QueryClient
实例,并将其提供给整个应用。
import 'package:flutter/material.dart';
import 'package:query_client/query_client.dart';
void main() {
final queryClient = QueryClient();
runApp(MyApp(queryClient: queryClient));
}
class MyApp extends StatelessWidget {
final QueryClient queryClient;
const MyApp({Key? key, required this.queryClient}) : super(key: key);
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(queryClient: queryClient),
);
}
}
2. 使用 Query
进行数据查询
Query
是 query_client
中用于执行数据查询的类。你可以使用 Query
来获取数据,并管理查询的状态。
import 'package:flutter/material.dart';
import 'package:query_client/query_client.dart';
class MyHomePage extends StatelessWidget {
final QueryClient queryClient;
const MyHomePage({Key? key, required this.queryClient}) : super(key: key);
Future<String> fetchData() async {
await Future.delayed(Duration(seconds: 2)); // 模拟网络请求
return 'Hello, Query Client!';
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Query Client Example'),
),
body: Center(
child: Query<String>(
queryClient: queryClient,
queryKey: 'exampleQuery',
queryFn: fetchData,
builder: (context, state) {
if (state.isLoading) {
return CircularProgressIndicator();
} else if (state.hasError) {
return Text('Error: ${state.error}');
} else {
return Text('Data: ${state.data}');
}
},
),
),
);
}
}
3. 使用 Mutation
进行数据更新
Mutation
是 query_client
中用于执行数据更新的类。你可以使用 Mutation
来提交数据,并管理更新的状态。
import 'package:flutter/material.dart';
import 'package:query_client/query_client.dart';
class MyHomePage extends StatelessWidget {
final QueryClient queryClient;
const MyHomePage({Key? key, required this.queryClient}) : super(key: key);
Future<String> fetchData() async {
await Future.delayed(Duration(seconds: 2)); // 模拟网络请求
return 'Hello, Query Client!';
}
Future<void> updateData(String newData) async {
await Future.delayed(Duration(seconds: 2)); // 模拟网络请求
// 这里可以执行实际的更新操作
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Query Client Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Query<String>(
queryClient: queryClient,
queryKey: 'exampleQuery',
queryFn: fetchData,
builder: (context, state) {
if (state.isLoading) {
return CircularProgressIndicator();
} else if (state.hasError) {
return Text('Error: ${state.error}');
} else {
return Text('Data: ${state.data}');
}
},
),
Mutation<void, String>(
queryClient: queryClient,
mutationFn: updateData,
builder: (context, mutate, state) {
return ElevatedButton(
onPressed: () {
mutate('New Data');
},
child: state.isLoading
? CircularProgressIndicator()
: Text('Update Data'),
);
},
),
],
),
),
);
}
}