Flutter自定义UI构建插件body_builder的使用
Flutter 自定义 UI 构建插件 body_builder
的使用
BodyBuilder
是一个管理数据加载的组件。对于每种情况,该组件会根据包含所有必要信息的 BodyState
进行重建,以便正确显示相应的组件。
开始之前
BodyBuilder
通过三种不同的方式管理数据加载:状态(state)、缓存(cache)和数据(data):
- 状态(state) 是一个
ChangeNotifier
,其中包含已检索的数据。BodyBuilder
会监听它并在状态更改时进行重建。 - 缓存(cache) 是一个
Future
,如果状态为空,则在显示加载组件之前调用它并返回一个可空值。 - 数据(data) 是一个
Future
,如果状态为空,则调用它。如果发生错误,则显示错误组件。
分页数据也得到了支持(参见示例应用)。
简单使用
以下是如何使用 BodyBuilder
组件的一个简单示例。
如果你希望 BodyBuilder
显示加载和错误组件:
BodyBuilder(
providers: [
BodyProvider(
state: _state,
cache: _cacheProvider,
data: _dataProvider,
)
],
builder: (String data) => Center(child: Text(data)),
);
如果你希望自行管理加载和错误组件,可以使用 customBuilder
,它提供了 BodyState
来显示正确的组件:
BodyBuilder(
key: _key,
providers: [
BodyProvider(
state: _state,
cache: _cacheProvider,
data: _dataProvider,
)
],
customBuilder: (BodyState state) => Center(child: Text('data: ${state.data} (isCache: ${state.isCache}), error: ${state.error}, loading: ${state.loading}')),
);
你可以通过 loadingBuilder
和 errorBuilder
覆盖默认的加载和错误组件。
你还可以通过 BodyBuilder.setDefaultConfig
配置所有 BodyBuilder
。
工作原理
状态提供器(StateProvider)
有几个状态提供器可以帮助你在不同情况下处理数据。
-
SimpleStateProvider 可以用于处理单个值。(例如:从服务器获取配置)
BodyProvider( state: context.read<BasicSampleState>(), ... )
-
RelatedStateProvider 是一个带有你选择键的
SimpleStateProvider
的映射。(例如:你想按用户ID排序获取多个用户)BodyProvider( state: context.read<MultiProviderSampleState>().byId(...), ... )
-
PaginatedState 允许你检索分页数据列表。(查看示例应用)
BodyProvider( state: context.read<YourRelatedPaginatedStates>().byId(...), ... )
-
ChangeNotifierExt.map 允许你通过
map
函数将任何ChangeNotifier
转换为StateProvider
。final StateProvider<...> state = context.read<YouState>().map((YouState state) => state.someValue);
额外信息
如果你发现了一个 bug 或者想要添加一个功能,请在 GitHub 上提交问题 这里。
完整示例 Demo
以下是完整的示例代码:
import 'package:body_builder/body_builder.dart';
import 'package:body_builder_example/basic_sample_page.dart';
import 'package:body_builder_example/custom_builder_page.dart';
import 'package:body_builder_example/multi_providers_page.dart';
import 'package:body_builder_example/paginated_page.dart';
import 'package:body_builder_example/search_sample_page.dart';
import 'package:body_builder_example/states.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
BodyBuilder.setDefaultConfig(debugLogsEnabled: true);
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => BasicSampleState()),
ChangeNotifierProvider(create: (_) => MultiProviderSampleState()),
ChangeNotifierProvider(create: (_) => PaginatedSampleState()),
ChangeNotifierProvider(create: (_) => SearchSampleState()),
],
child: MaterialApp(
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
appBarTheme: AppBarTheme(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
),
),
home: const MyHomePage(title: 'Body Builder - Example'),
),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
[@override](/user/override)
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const BasicBodyBuilderPage(),
),
);
},
child: const Text('Basic example'),
),
ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const CustomBuilderPage(),
),
);
},
child: const Text('Custom builder example'),
),
ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const MultiProversPage(),
),
);
},
child: const Text('Multi providers example'),
),
ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const PaginatedPage(),
),
);
},
child: const Text('Pagination example'),
),
ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const SearchSamplePage(),
),
);
},
child: const Text('Search example'),
),
const Divider(),
ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.orange),
),
onPressed: () {
context.read<BasicSampleState>().clear();
context.read<MultiProviderSampleState>().clear();
context.read<PaginatedSampleState>().clear();
context.read<SearchSampleState>().clear();
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('All states cleared!')),
);
},
child: const Text('Clear states'),
),
],
),
),
);
}
}
更多关于Flutter自定义UI构建插件body_builder的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html