Flutter数据变换插件flutter_mutation的使用
Flutter数据变换插件flutter_mutation的使用
特性
- 使用hook轻松处理Flutter中的异步状态
开始使用
在pubspec.yaml
文件中添加依赖:
dependencies:
flutter_mutation: ^latest
使用示例
异步获取
以下示例展示了如何使用flutter_mutation
进行异步数据获取。
class GettingStartedPage extends HookWidget {
const GettingStartedPage({super.key});
static MaterialPageRoute createRoute() {
return MaterialPageRoute(builder: (context) {
return const GettingStartedPage();
});
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("getting started page"),
),
body: Center(
child: Stack(
alignment: Alignment.center,
children: [
HookBuilder(builder: (context) {
final loading = useMutationLoading(keyOf: "get");
return Visibility(
visible: loading, child: const CircularProgressIndicator());
}),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
HookBuilder(builder: (context) {
final data = useMutationLoading(keyOf: "get");
return Text("loading:$data");
}),
HookBuilder(builder: (context) {
final data = useMutationData(keyOf: "get");
return Text("data:$data");
}),
HookBuilder(builder: (context) {
final data = useMutationInitialized(keyOf: "get");
return Text("initialized:$data");
}),
HookBuilder(builder: (context) {
final data = useMutationError(keyOf: "get");
return Text("error:$data");
}),
TextButton(
onPressed: () async {
MutationKey.of("get").mutate(GettingStartedApi.get());
},
child: const Text("mutate")),
],
),
],
),
),
);
}
}
分页
以下示例展示了如何使用flutter_mutation
实现分页功能。
class PaginationPage extends HookWidget {
const PaginationPage({super.key});
static MaterialPageRoute createRoute() {
return MaterialPageRoute(builder: (context) {
return const PaginationPage();
});
}
[@override](/user/override)
Widget build(BuildContext context) {
print("cache:${MutationCache.instance}");
final mutationKey = useMutationKey<PaginationResponse>();
final onPressMore = useCallback(() {
PaginationApi.getList(mutationKey.data?.nextPageKey)
.mutate(mutationKey, append: true);
}, []);
final onRefresh = useCallback(() async {
return PaginationApi.getList().mutate(mutationKey);
}, []);
return Scaffold(
appBar: AppBar(
title: const Text("pagination page"),
),
body: RefreshIndicator(
onRefresh: onRefresh,
child: HookBuilder(builder: (context) {
final dataList = useMutationDataList(key: mutationKey);
final loading = useMutationLoading(
key: mutationKey, lazyInitialData: PaginationApi.getList);
final list = useMemoized(
() => dataList.expand((element) => element.list).toList(),
[dataList]);
return ListView.builder(
itemCount: list.length + 1,
itemBuilder: (context, index) {
if (index == list.length) {
return TextButton(
onPressed: loading ? null : onPressMore,
child: loading
? const Text("Loading...")
: const Text("More"));
}
final item = list[index];
return ListTile(
title: Text(item),
);
},
);
}),
),
);
}
}
缓存
以下示例展示了如何使用flutter_mutation
进行缓存管理。
final MutationKey<CachingResponse> cacheKey = MutationKey.of("aa");
class CachingPage extends HookWidget {
const CachingPage({super.key});
static MaterialPageRoute createRoute() {
return MaterialPageRoute(builder: (context) {
return const CachingPage();
});
}
[@override](/user/override)
Widget build(BuildContext context) {
print("cache:${MutationCache.instance}");
useEffect(() {
return cacheKey.observe(onClose: (mutation) {
print("closed:$mutation");
});
}, [cacheKey]);
final onPressRefresh = useCallback(() async {
await CachingApi.get().mutate(cacheKey);
}, []);
return Scaffold(
appBar: AppBar(
title: const Text("caching page"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
HookBuilder(
key: UniqueKey(),
builder: (context) {
final loading = useMutationLoading(key: cacheKey);
return loading
? const Text("Loading...")
: const Text("complete");
}),
HookBuilder(builder: (context) {
final data = useMutationData(
key: cacheKey, lazyInitialData: CachingApi.get);
return Text("title:${data?.title}");
}),
TextButton(onPressed: onPressRefresh, child: const Text("refresh")),
TextButton(
onPressed: () {
Navigator.of(context).push(CachingNextPage.createRoute());
},
child: const Text("next"))
],
),
),
);
}
}
class CachingNextPage extends HookWidget {
const CachingNextPage({super.key});
static MaterialPageRoute createRoute() {
return MaterialPageRoute(builder: (context) {
return const CachingNextPage();
});
}
[@override](/user/override)
Widget build(BuildContext context) {
final onPressRefresh = useCallback(() async {
await CachingApi.get().mutate(cacheKey);
}, []);
return Scaffold(
appBar: AppBar(
title: const Text("caching next page"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
HookBuilder(builder: (context) {
final loading = useMutationLoading(key: cacheKey);
return loading
? const Text("Loading...")
: const Text("complete");
}),
HookBuilder(builder: (context) {
final data = useMutationData(
lazyInitialData: CachingApi.get, key: cacheKey);
return Text(
"nickname: ${data?.nickname}\ncontents: ${data?.contents}");
}),
TextButton(onPressed: onPressRefresh, child: const Text("refresh"))
],
),
),
);
}
}
全局状态
以下示例展示了如何使用flutter_mutation
管理全局状态。
class GlobalStateMutations {
static final authTokenKey = MutationKey<String>().retain(onOpen: (mutation) {
print("onOpen:$mutation");
}, onUpdateData: (data, {before}) {
print("onUpdateData:$data, $before");
});
}
class GlobalStatePage extends HookWidget {
const GlobalStatePage({super.key});
static MaterialPageRoute createRoute() {
return MaterialPageRoute(builder: (context) {
return const GlobalStatePage();
});
}
[@override](/user/override)
Widget build(BuildContext context) {
print("cache:${MutationCache.instance}");
final onPressLogin = useCallback(() {
GlobalStateApi.postLogin().mutate(GlobalStateMutations.authTokenKey);
}, []);
final onPressClear = useCallback(() {
GlobalStateMutations.authTokenKey.clear();
}, []);
return Scaffold(
appBar: AppBar(
title: const Text("global state page"),
),
body: Center(
child: Stack(
alignment: Alignment.center,
children: [
HookBuilder(builder: (context) {
final loading =
useMutationLoading(key: GlobalStateMutations.authTokenKey);
return Visibility(
visible: loading, child: const CircularProgressIndicator());
}),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
HookBuilder(builder: (context) {
final data =
useMutationData(key: GlobalStateMutations.authTokenKey);
return Text("authToken:$data");
}),
TextButton(onPressed: onPressLogin, child: const Text("login")),
TextButton(onPressed: onPressClear, child: const Text("clear"))
],
),
],
),
),
);
}
}
懒加载
以下示例展示了如何使用flutter_mutation
进行懒加载操作。
final MutationKey<String> lazyMutateKey =
MutationKey<String>().retain(onUpdateData: (data, {before}) {
print("onUpdateData:$data");
}, onUpdateLoading: (loading) {
print("onUpdateLoading:$loading");
});
class LazyMutatePage extends HookWidget {
const LazyMutatePage({super.key});
static MaterialPageRoute createRoute() {
return MaterialPageRoute(builder: (context) {
return const LazyMutatePage();
});
}
[@override](/user/override)
Widget build(BuildContext context) {
print("cache:${MutationCache.instance}");
return Scaffold(
appBar: AppBar(
title: const Text("lazy mutate page"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
HookBuilder(builder: (context) {
final loading = useMutationLoading<String>(key: lazyMutateKey);
return loading
? const Text("Loading...")
: const Text("complete");
}),
HookBuilder(builder: (context) {
final data = useMutationData(
key: lazyMutateKey, lazyInitialData: LazyMutateApi.get);
return Text("data:$data");
}),
TextButton(
onPressed: () {
LazyMutateApi.get().mutate(lazyMutateKey);
},
child: const Text("refresh")),
TextButton(
onPressed: () {
lazyMutateNextKey.lazyMutate(LazyMutateApi.get2);
},
child: const Text("lazyMutateNext")),
TextButton(
onPressed: () {
Navigator.of(context).push(LazyMutateNextPage.createRoute());
},
child: const Text("next"))
],
),
),
);
}
}
final MutationKey<String> lazyMutateNextKey =
MutationKey<String>().retain(onUpdateData: (data, {before}) {
print("onUpdateData:$data");
}, onUpdateLoading: (loading) {
print("onUpdateLoading:$loading");
});
class LazyMutateNextPage extends HookWidget {
const LazyMutateNextPage({super.key});
static MaterialPageRoute createRoute() {
return MaterialPageRoute(builder: (context) {
return const LazyMutateNextPage();
});
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("lazy mutate next page"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
HookBuilder(builder: (context) {
final loading = useMutationLoading(key: lazyMutateNextKey);
return loading
? const Text("Loading...")
: const Text("complete");
}),
HookBuilder(builder: (context) {
final data = useMutationData(key: lazyMutateNextKey);
return Text("data: $data");
}),
TextButton(
onPressed: () {
lazyMutateNextKey.lazyMutate(LazyMutateApi.get2);
},
child: const Text("lazyMutate")),
TextButton(
onPressed: () {
lazyMutateKey.lazyMutate(LazyMutateApi.get);
},
child: const Text("lazyMutateBefore"))
],
),
),
);
}
}
更多关于Flutter数据变换插件flutter_mutation的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter数据变换插件flutter_mutation的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,flutter_mutation
是一个用于在 Flutter 中进行数据变换的插件。虽然它不是一个官方或广泛使用的插件(请注意,由于插件的流行度和维护状态可能会随时间变化,以下信息可能需要根据实际情况调整),但假设它提供了类似数据映射、转换等功能,我们可以基于常见的数据变换需求给出一个示例。
通常,数据变换可能涉及将 JSON 数据映射到 Dart 模型、数据过滤、数据格式化等操作。虽然 flutter_mutation
的具体 API 可能有所不同,但我们可以模拟一个类似功能的实现。
以下是一个假设的 flutter_mutation
使用示例,这里我们将使用自定义的代码来模拟数据变换的过程,因为实际的 flutter_mutation
插件细节可能未知。
示例:将 JSON 数据映射到 Dart 模型并进行变换
1. 定义 Dart 模型
首先,我们定义一个 Dart 模型类来映射 JSON 数据。
class User {
String name;
int age;
String email;
User({required this.name, required this.age, required this.email});
// 从 JSON 数据创建 User 实例的工厂方法
factory User.fromJson(Map<String, dynamic> json) {
return User(
name: json['name'] as String,
age: json['age'] as int,
email: json['email'] as String,
);
}
// 将 User 实例转换为 JSON 数据
Map<String, dynamic> toJson() {
return {
'name': name,
'age': age,
'email': email,
};
}
}
2. 数据变换逻辑(模拟 flutter_mutation
的功能)
接下来,我们编写一些数据变换逻辑,比如将用户列表中的年龄增加一岁,或者将电子邮件地址格式化为小写。
List<User> transformUserList(List<User> users) {
return users.map((user) {
// 增加年龄
int newAge = user.age + 1;
// 格式化电子邮件地址
String formattedEmail = user.email.toLowerCase();
// 返回一个新的 User 实例,包含变换后的数据
return User(
name: user.name,
age: newAge,
email: formattedEmail,
);
}).toList();
}
3. 使用变换逻辑
最后,我们模拟从某处获取 JSON 数据,将其转换为 Dart 模型列表,并应用变换逻辑。
void main() {
// 假设这是从服务器获取的原始 JSON 数据
String jsonData = '''
[
{"name": "Alice", "age": 30, "email": "Alice@example.COM"},
{"name": "Bob", "age": 25, "email": "BOB@example.com"}
]
''';
// 将 JSON 数据转换为 List<Map<String, dynamic>>
List<dynamic> jsonList = jsonDecode(jsonData);
// 将 List<Map<String, dynamic>> 转换为 List<User>
List<User> userList = jsonList.map((json) => User.fromJson(json as Map<String, dynamic>)).toList();
// 应用数据变换逻辑
List<User> transformedUserList = transformUserList(userList);
// 输出变换后的数据
transformedUserList.forEach((user) {
print('Name: ${user.name}, Age: ${user.age}, Email: ${user.email}');
});
}
总结
虽然这个示例没有直接使用假设的 flutter_mutation
插件,但它展示了在 Flutter 中进行数据变换的常见方法,包括定义数据模型、编写变换逻辑以及应用这些逻辑。如果 flutter_mutation
插件确实存在并具有类似功能,其使用方式可能会更加简洁或高效,但基本原理是相似的。
请注意,实际开发中应参考 flutter_mutation
(如果可用)的官方文档和 API 以获取准确的使用方法和最佳实践。