Flutter上下文提供插件build_context_provider的使用
Flutter上下文提供插件build_context_provider的使用
build_context_provider
是一个允许你在Flutter widgets之外运行需要 BuildContext
的函数的包。这使得在没有直接访问到 BuildContext
的地方(例如业务逻辑层或服务类)调用与UI交互的方法变得可能。下面我们将详细介绍如何安装、使用以及一些示例代码来帮助你更好地理解这个插件。
安装
要使用 build_context_provider
,首先你需要将其添加到你的项目依赖中。然后,在应用的根部放置 ListenerThatRunsFunctionsWithBuildContext()
组件以确保所有需要 BuildContext
的操作都能正常工作。
return Stack(
children: [
child,
const ListenerThatRunsFunctionsWithBuildContext(),
],
);
使用
你可以通过 BuildContextProvider.call()
方法包装任何你想执行且需要 BuildContext
的函数。这样做的好处是,这些函数可以在不需要 BuildContext
的地方被调用。
BuildContextProvider.call(
(context) => Navigator.pushNamed(context, '/somewhere'),
);
示例
这里有一个完整的例子,展示了如何在一个不直接拥有 BuildContext
的地方导航到另一个页面:
class GoToProfilePage {
static void call() {
BuildContextProvider.call(
(context) => Navigator.pushNamed(context, '/profile'),
);
}
}
// 这行代码可以在任何地方使用。如你所见,你不再受限于构建上下文。
GoToProfilePage.call();
如果你需要从函数返回值,可以通过包裹你的函数并捕获其结果来实现:
bool aValueToBeReturnedFromTheFunction = false;
bool functionThatReturnsValue(BuildContext context) {
Navigator.of(context).pushNamed('/profile');
return true;
}
void aFunctionThatCapturesReturnedValue(BuildContext context) {
aValueToBeReturnedFromTheFunction = functionThatReturnsValue(context);
}
BuildContextProvider()(aFunctionThatCapturesReturnedValue);
expect(aValueToBeReturnedFromTheFunction, isTrue);
设计原则
- 无外部库:此包尽量减少对外部库的依赖。
- 单一职责:只做一件事,并且做好这件事。
完整示例代码
接下来是一个更全面的例子,它演示了如何在实际项目中使用 build_context_provider
包。此示例包括两个屏幕之间的导航和显示SnackBar的功能,而这些功能都是在没有直接访问到 BuildContext
的情况下完成的。
import 'package:flutter/material.dart';
import 'package:build_context_provider/build_context_provider.dart';
void _displaySnackbar() {
BuildContextProvider()((context) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: _Snackbar(),
),
);
});
}
class _App extends StatelessWidget {
const _App({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: '/first',
routes: {
'/first': (context) => const _Layout(child: _FirstScreen()),
'/second': (context) => const _Layout(child: _SecondScreen()),
},
);
}
}
class _FirstScreen extends StatelessWidget {
const _FirstScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Center(
child: Text('First screen'),
);
}
}
class _SecondScreen extends StatelessWidget {
const _SecondScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Center(
child: Text('Second screen'),
);
}
}
class _Layout extends StatelessWidget {
final Widget child;
const _Layout({Key? key, required this.child}) : super(key: key);
@override
Widget build(BuildContext context) {
final buildContextProvider = BuildContextProvider();
return Scaffold(
body: SafeArea(
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
child,
const ListenerThatRunsFunctionsWithBuildContext(),
],
),
),
persistentFooterButtons: [
ElevatedButton(
child: const Text('Go to first screen'),
onPressed: () => buildContextProvider(
(context) => Navigator.pushNamed(context, '/first'),
),
),
ElevatedButton(
child: const Text('Go to second screen'),
onPressed: () => buildContextProvider(
(context) => Navigator.pushNamed(context, '/second'),
),
),
],
floatingActionButton: const FloatingActionButton(
child: Icon(Icons.add),
onPressed: _displaySnackbar,
),
);
}
}
class _Snackbar extends StatelessWidget {
const _Snackbar({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return SizedBox(
height: 100,
child: Column(
children: const [
Text('If you see this snackbar then everything is working properly.'),
Text(
'Function that creates this snackbar was called without a build context.',
)
],
),
);
}
}
void main(List<String> args) {
runApp(const _App());
}
这段代码创建了一个简单的Flutter应用程序,其中包含两个屏幕(_FirstScreen
和 _SecondScreen
),并且可以通过底部按钮进行切换。此外,还有一个浮动按钮用于展示SnackBar,即使是在没有直接获取到 BuildContext
的地方也可以成功触发。
更多关于Flutter上下文提供插件build_context_provider的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter上下文提供插件build_context_provider的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在Flutter中,build_context_provider
是一个有用的插件,它允许你在应用的不同部分之间共享和访问 BuildContext
。这在某些场景下非常有用,比如当你需要从深层组件中访问导航栏或执行与UI相关的操作时。
以下是一个使用 build_context_provider
的基本示例,展示了如何设置和使用它来共享 BuildContext
。
1. 添加依赖
首先,你需要在 pubspec.yaml
文件中添加 build_context_provider
的依赖:
dependencies:
flutter:
sdk: flutter
build_context_provider: ^x.y.z # 请替换为最新版本号
然后运行 flutter pub get
来获取依赖。
2. 设置 BuildContextProvider
在你的应用顶层(通常是 MyApp
或 MaterialApp
组件中),设置 BuildContextProvider
:
import 'package:flutter/material.dart';
import 'package:build_context_provider/build_context_provider.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BuildContextProvider(
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
),
);
}
}
3. 使用 BuildContext
现在,你可以在任何需要的地方使用 BuildContextProvider.of(context)
来获取 BuildContext
。以下是一个简单的例子,展示如何在深层组件中使用它:
import 'package:flutter/material.dart';
import 'package:build_context_provider/build_context_provider.dart';
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Demo Home Page'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Counter(),
ElevatedButton(
onPressed: () {
// 使用 BuildContextProvider.of(context) 获取上下文并导航
final navigator = BuildContextProvider.of(context).navigator;
navigator.push(
MaterialPageRoute(builder: (context) => SecondPage()),
);
},
child: Text('Go to Second Page'),
),
],
),
),
);
}
}
class Counter extends StatefulWidget {
@override
_CounterState createState() => _CounterState();
}
class _CounterState extends State<Counter> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
);
}
}
class SecondPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 这里你也可以使用 BuildContextProvider.of(context) 获取上下文进行其他操作
return Scaffold(
appBar: AppBar(
title: Text('Second Page'),
),
body: Center(
child: Text('This is the second page!'),
),
);
}
}
在这个例子中,我们在 MyApp
中设置了 BuildContextProvider
,然后在 MyHomePage
的按钮点击事件中,通过 BuildContextProvider.of(context).navigator
获取了导航器并导航到了 SecondPage
。
请注意,BuildContextProvider
提供的 navigator
只是一个简单的示例,它可能并不是直接提供的属性。通常,你会通过其他方式(如全局状态管理或依赖注入)来共享和访问导航器或其他需要跨组件共享的对象。这个插件的核心功能是在整个应用树中共享 BuildContext
,但你需要根据自己的需求来决定如何使用它。