如何在 Widget 之外派发 Bloc 事件?
How to dispatch Bloc events outside of Widget?
我是 Bloc 架构的新手,最近看了一些教程。我有一个 StatelessWidget 页面,在里面我使用 BlocProvider 在我的 UI 中初始化 Bloc。它会根据状态变化 return 不同的小部件。
但即使在教程中,他们也仅从其他 Widget 发送事件(例如通过按下按钮)。但是在我的情况下,我需要在 Bloc Event 中的 Widget 之外调用 init API call。
如果我在其他 Widget 中,我可以调用 BlocProvider.of<FirstTabBloc>(context).dispatch(GetUserProfile());
但我不能在 main() 中调用它,因为上下文不是来自 Widget。
代码:
class FirstPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: firstTabElement(context),
),
appBar: EmptyAppBar(mainAppColor),
);
}
BlocProvider<FirstTabBloc> firstTabElement(BuildContext context) {
return BlocProvider(
builder: (_) => sl<FirstTabBloc>(),
child: Expanded(
child: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: Column(
children: <Widget>[
Stack(
children: [
//Main Background
Column(children: <Widget>[
//Top part
Container(
constraints: BoxConstraints(
minHeight: 120,
),
width: MediaQuery.of(context).size.width,
height: 300,
decoration: new BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: ticketGradient,
),
),
),
// Bottom part - white
Container(
color: basicWhite,
),
]),
//content above background
BlocBuilder<FirstTabBloc, FirstTabState>(
builder: (context, state) {
if (state is Uninitialized) {
return WalletWidget(
credit: formatPrice(0),
currency: '€',
);
} else if (state is Loading) {
return LoadingWidget();
} else if (state is Loaded) {
Wallet currWallet = state.profile.getWalletByClient(clientId);
return WalletWidget(
credit: formatPrice(currWallet.value),
currency: formatCurrency(currWallet.currency),
);
} else if (state is Error) {
return MessageDisplay(
message: state.message,
);
}
},
),
],
),
],
),
)));
}
}
您需要使用其他方式获取区块。
BlocProvider.of(context)
在后台使用 Provider
。 Provider is a flutter package, that wraps InheritedWidget
. InheritedWidget 是 flutter 小部件,它通过上下文将数据向下传递到小部件树。
所以你需要另一种方式。例如,您可以使用 get_it 库。它是 Service Locator
.
的飞镖实现
widget 之外的 bloc 的简单示例
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
final bloc = CounterBloc();
void main() {
bloc.add(CounterEvent.increment);
bloc.add(CounterEvent.increment);
bloc.add(CounterEvent.increment);
bloc.add(CounterEvent.increment);
runApp(
MyApp(),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
body: SafeArea(
child: MyHomePage(),
),
),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (_) => bloc,
child: CounterPage(),
);
}
}
class CounterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Counter')),
body: BlocBuilder<CounterBloc, int>(
builder: (_, count) {
return Center(
child: Text('$count', style: Theme.of(context).textTheme.headline1),
);
},
),
floatingActionButton: Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(vertical: 5.0),
child: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () =>
context.bloc<CounterBloc>().add(CounterEvent.increment),
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 5.0),
child: FloatingActionButton(
child: const Icon(Icons.remove),
onPressed: () =>
context.bloc<CounterBloc>().add(CounterEvent.decrement),
),
),
],
),
);
}
}
enum CounterEvent { increment, decrement }
class CounterBloc extends Bloc<CounterEvent, int> {
CounterBloc() : super(0);
@override
Stream<int> mapEventToState(CounterEvent event) async* {
switch (event) {
case CounterEvent.decrement:
yield state - 1;
break;
case CounterEvent.increment:
yield state + 1;
break;
default:
addError(Exception('unsupported event'));
}
}
}
在 get_it 中注册您的集团。然后你可以在没有上下文的情况下获取和使用它。
我认为你需要了解
dispatch renamed to add
> There were core api changes introduced into 1.0.0:
bloc.state.listen -> bloc.listen
bloc.currentState -> bloc.state
bloc.dispatch -> bloc.add
bloc.dispose -> bloc.close
查看 https://link.medium.com/qnfMcEcW00 了解更多详情。
希望有帮助
我是 Bloc 架构的新手,最近看了一些教程。我有一个 StatelessWidget 页面,在里面我使用 BlocProvider 在我的 UI 中初始化 Bloc。它会根据状态变化 return 不同的小部件。
但即使在教程中,他们也仅从其他 Widget 发送事件(例如通过按下按钮)。但是在我的情况下,我需要在 Bloc Event 中的 Widget 之外调用 init API call。
如果我在其他 Widget 中,我可以调用 BlocProvider.of<FirstTabBloc>(context).dispatch(GetUserProfile());
但我不能在 main() 中调用它,因为上下文不是来自 Widget。
代码:
class FirstPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: firstTabElement(context),
),
appBar: EmptyAppBar(mainAppColor),
);
}
BlocProvider<FirstTabBloc> firstTabElement(BuildContext context) {
return BlocProvider(
builder: (_) => sl<FirstTabBloc>(),
child: Expanded(
child: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: Column(
children: <Widget>[
Stack(
children: [
//Main Background
Column(children: <Widget>[
//Top part
Container(
constraints: BoxConstraints(
minHeight: 120,
),
width: MediaQuery.of(context).size.width,
height: 300,
decoration: new BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: ticketGradient,
),
),
),
// Bottom part - white
Container(
color: basicWhite,
),
]),
//content above background
BlocBuilder<FirstTabBloc, FirstTabState>(
builder: (context, state) {
if (state is Uninitialized) {
return WalletWidget(
credit: formatPrice(0),
currency: '€',
);
} else if (state is Loading) {
return LoadingWidget();
} else if (state is Loaded) {
Wallet currWallet = state.profile.getWalletByClient(clientId);
return WalletWidget(
credit: formatPrice(currWallet.value),
currency: formatCurrency(currWallet.currency),
);
} else if (state is Error) {
return MessageDisplay(
message: state.message,
);
}
},
),
],
),
],
),
)));
}
}
您需要使用其他方式获取区块。
BlocProvider.of(context)
在后台使用 Provider
。 Provider is a flutter package, that wraps InheritedWidget
. InheritedWidget 是 flutter 小部件,它通过上下文将数据向下传递到小部件树。
所以你需要另一种方式。例如,您可以使用 get_it 库。它是 Service Locator
.
widget 之外的 bloc 的简单示例
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
final bloc = CounterBloc();
void main() {
bloc.add(CounterEvent.increment);
bloc.add(CounterEvent.increment);
bloc.add(CounterEvent.increment);
bloc.add(CounterEvent.increment);
runApp(
MyApp(),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
body: SafeArea(
child: MyHomePage(),
),
),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (_) => bloc,
child: CounterPage(),
);
}
}
class CounterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Counter')),
body: BlocBuilder<CounterBloc, int>(
builder: (_, count) {
return Center(
child: Text('$count', style: Theme.of(context).textTheme.headline1),
);
},
),
floatingActionButton: Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(vertical: 5.0),
child: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () =>
context.bloc<CounterBloc>().add(CounterEvent.increment),
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 5.0),
child: FloatingActionButton(
child: const Icon(Icons.remove),
onPressed: () =>
context.bloc<CounterBloc>().add(CounterEvent.decrement),
),
),
],
),
);
}
}
enum CounterEvent { increment, decrement }
class CounterBloc extends Bloc<CounterEvent, int> {
CounterBloc() : super(0);
@override
Stream<int> mapEventToState(CounterEvent event) async* {
switch (event) {
case CounterEvent.decrement:
yield state - 1;
break;
case CounterEvent.increment:
yield state + 1;
break;
default:
addError(Exception('unsupported event'));
}
}
}
在 get_it 中注册您的集团。然后你可以在没有上下文的情况下获取和使用它。
我认为你需要了解 dispatch renamed to add
> There were core api changes introduced into 1.0.0:
bloc.state.listen -> bloc.listen
bloc.currentState -> bloc.state
bloc.dispatch -> bloc.add
bloc.dispose -> bloc.close
查看 https://link.medium.com/qnfMcEcW00 了解更多详情。 希望有帮助