Flutter自定义UI组件插件pottery的使用
Flutter自定义UI组件插件pottery的使用
本包提供了两个小部件,Pottery
和 LocalPottery
,用于根据 Flutter 中的小部件生命周期管理 Pot
(单类型依赖注入容器)的生命周期。
为什么这比 Pot 的范围功能更好?
来自 package:pot
的 Pot
本身具有作用域功能,但它是一个 Dart 包,而不是专门为 Flutter 设计的。
Pottery
是一个弥补这一点的工具。它利用小部件生命周期来限制 Pot
的作用域。在 Flutter 中更自然且更不容易出错。
这将如何使事情变得更好?
虽然你可以从任何地方访问存储在全局变量中的 Pot
非常方便,但这给了你太多自由,让你不知道如何在 Flutter 应用中管理 Pot
。例如,你可能会很容易失去对应用代码中特定 Pot
使用位置的跟踪。
Pottery
可以使 Pot
的管理类似于使用 package:provider
。参见下文中的示例。
示例
- Counters - 简单示例
- pub.dev 探索器 - 高级示例
开始使用
在 pubspec.yaml
文件中添加以下依赖:
dependencies:
pottery: ^x.x.x
使用
Pottery
首先创建一个作为“挂起”的 Pot
,如果在应用启动时还不需要使用它。通常将其分配给一个全局变量。
final counterNotifierPot = Pot.pending<CounterNotifier>(
disposer: (notifier) => notifier.dispose(),
);
使用 Pottery
并在需要开始使用 Pot
之前指定一个工厂。
Widget build(BuildContext context) {
// counterNotifierPot 没有工厂。
// 在此处调用 `counterNotifierPot()` 会抛出 PotNotReadyException 异常。
...
return Scaffold(
body: Pottery(
pots: {
counterNotifierPot: CounterNotifier.new,
},
// 在第一次调用此构建器之前,上面的 pots 参数中的新工厂已经准备好。
builder: (context) {
// 现在可以使用 counterNotifierPot 的方法和 getter。
final count = counterNotifierPot();
...
},
),
),
);
pots
是一个包含 Pot
和工厂键值对的 Map。每个工厂在之后成为相应 Pot
的可用对象。
想象一下 Pottery
类似于 provider
包中的 MultiProvider
,尽管它们内部的工作方式非常不同。
- MultiProvider
- 创建对象并提供它们,以便它们在树的下方可用。
- Pottery
- 替换工厂以使
Pot
在该点之后可用。 - 小部件树仅用于管理工厂和
Pot
中对象的生命周期,因此Pot
仍然可以在树外可用。
- 替换工厂以使
从树中移除 Pottery
(例如,从使用 Pottery
的页面导航回来)会重置 pots
映射中的所有 Pot
并替换它们的工厂,以抛出 PotNotReadyException
异常。
注意:
如果目标 Pot
不是挂起的,并且在其创建时已存在对象,则 Pottery
会立即替换该对象及其工厂。
LocalPottery
此小部件为现有 Pot
定义新的工厂,以创建仅在子树中可用的对象。
重要的是,现有 Pot
的工厂不会被替换,而是为这些 Pot
分配新的单独工厂供本地使用。因此,调用 Pot
仍然会返回全局持有的对象。使用 NearestPotOf.of()
获取本地对象。下面的示例说明了这种行为。
final fooPot = Pot(() => Foo(111));
class ParentWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return LocalPottery(
pots: {
fooPot: () => Foo(222),
},
builder: (context) {
print(fooPot()); // 输出 111
print(fooPot.of(context)); // 输出 222
return ChildWidget();
},
);
}
}
class ChildWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
print(fooPot()); // 输出 111
print(fooPot.of(context)); // 输出 222
...
}
}
有关更多实际用例,请参阅 main2.dart 和 LocalPottery 文档。
请注意,LocalPottery
和 Pottery
之间有几个重要的区别:
- 对象在
LocalPottery
创建时立即创建,而不是在首次访问Pot
中的对象时。 - 如前所述,使用
LocalPottery
创建的对象只能通过NearestPotOf.of()
访问。 - 使用
LocalPottery
创建的对象不会在LocalPottery
从树中移除时自动销毁。使用disposer
指定清理它们的回调函数。下面是一个示例,其中disposer
函数清理所有ChangeNotifier
子类型。
LocalPottery(
pots: {
myChangeNotifier: () => MyChangeNotifier(),
intValueNotifier: () => ValueNotifier(111),
},
disposer: (pots) {
pots.values.whereType<ChangeNotifier>().forEach((v) => v.dispose());
},
builder: (context) { ... },
)
注意事项
确保指定返回正确类型的工厂
传递给 pots
的键值对不是类型安全的。
在以下示例中,一个返回 int
值的函数被指定为 String
类型的 Pot
的新工厂。虽然显然是错误的,但静态分析不会告诉你这个错误。错误只会在运行时发生。
final stringPot = Pot.pending<String>();
pots: {
stringPot: () => 123,
}
更多关于Flutter自定义UI组件插件pottery的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter自定义UI组件插件pottery的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter中使用自定义UI组件插件pottery
的一个代码示例。pottery
是一个假想的Flutter插件,用于展示自定义UI组件。由于pottery
并非一个真实存在的官方或广泛使用的插件,我将模拟一个类似的场景,展示如何集成和使用一个自定义UI组件插件。
假设pottery
插件提供了一个自定义的按钮组件CustomButton
,我们可以按照以下步骤来使用它。
1. 添加依赖
首先,在你的pubspec.yaml
文件中添加pottery
插件的依赖(注意:这里pottery
是假设的,你需要替换为实际的插件名称和版本)。
dependencies:
flutter:
sdk: flutter
pottery: ^1.0.0 # 假设的版本号
然后运行flutter pub get
来安装依赖。
2. 导入插件
在你的Dart文件中导入pottery
插件。
import 'package:pottery/pottery.dart';
3. 使用自定义组件
现在你可以在你的Flutter应用中使用pottery
插件提供的CustomButton
组件了。以下是一个简单的示例:
import 'package:flutter/material.dart';
import 'package:pottery/pottery.dart'; // 导入pottery插件
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Pottery Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Pottery Demo'),
),
body: Center(
child: CustomButton(
onPressed: () {
// 按钮点击事件处理
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Custom Button Clicked!')),
);
},
buttonText: 'Click Me',
buttonColor: Colors.blue,
textColor: Colors.white,
),
),
);
}
}
4. 假设的CustomButton
实现
由于pottery
是假设的,这里提供一个可能的CustomButton
实现,以便你理解其背后的概念。在实际使用中,你会从插件中获取这个组件的实现。
// 假设这是pottery插件中的CustomButton实现
class CustomButton extends StatelessWidget {
final VoidCallback onPressed;
final String buttonText;
final Color buttonColor;
final Color textColor;
const CustomButton({
Key? key,
required this.onPressed,
required this.buttonText,
this.buttonColor = Colors.blue,
this.textColor = Colors.white,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(buttonColor),
foregroundColor: MaterialStateProperty.all(textColor),
),
onPressed: onPressed,
child: Text(buttonText),
);
}
}
在实际应用中,你会从pottery
插件中获取CustomButton
的实现,而不是自己定义它。上面的代码只是为了展示如何定义和使用一个类似的自定义按钮组件。
总结
上述步骤展示了如何在Flutter项目中添加和使用一个假设的自定义UI组件插件pottery
。你需要将pottery
替换为实际的插件名称,并根据插件的文档调整代码。通常,插件的README文件会提供详细的安装和使用指南。