使用一个集团,一种分页形式的状态?
Using one bloc, one state in page-splitted form?
我有一个 单一表单 ,它根据用户体验和 UI 设计要求分为 3 个页面。结构如下所示:
MyApp
|
|- BlocProvider.of<MyBloc>(context)
|- PageA
| |- FormA
| |- InputA
| |- InputB
| |- InputC
| |- RaisedButton (Next button)
|
|- PageB
| |- FormA
| |- InputD
| |- InputE
| |- InputF
| |- RaisedButton (Back button)
| |- RaisedButton (Next button)
|
|- PageC
| |- FormA
| |- InputG
| |- InputH
| |- InputI
| |- RaisedButton (Back button)
| |- RaisedButton (Submit button)
我想传递相同的状态,并更新 RaisedButton
按钮的状态数据 onPressed
,而不用将我的树 包裹在 blocbuilder, bloclistener
或 blocconsumer
因为没有像在需要状态更改时重建小部件这样的事情。
我该怎么做?
NOTE
- Each form is a page, not a tabbar or pageview.
- I want only 1 bloc and 1 state to be shared across the page, not 1 bloc per page.
- I want this behavior simply because I'm actually avoid passing data from the constructor.
- Already tried
BlocProvider.of<MyBloc>(context).state
but it is not giving me access to the object.
我做了一个非常简单的例子希望对你有帮助。
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (_) => MyForm(),
child: MaterialApp(
title: 'Flutter Demo',
home: HomePage(),
),
);
}
}
class HomePage extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
BlocBuilder<MyForm, MyFromState>(
builder: (_, state) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('inputA: ${state.inputA}'),
Text('inputB: ${state.inputB}'),
Text('inputC: ${state.inputC}'),
Text('inputD: ${state.inputD}'),
Text('inputE: ${state.inputE}'),
Text('inputF: ${state.inputF}'),
],
);
},
),
Center(
child: RaisedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => FirstPage()),
);
},
child: Text('start'),
),
),
],
),
);
}
}
class FirstPage extends StatelessWidget {
Widget build(BuildContext context) {
var bloc = BlocProvider.of<MyForm>(context);
return Scaffold(
body: Center(
child: RaisedButton(
onPressed: () {
bloc.add(FirstPageSubmitEvent(
inputA: 'text1',
inputB: 'text2',
));
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondPage()),
);
},
child: Text('page 2'),
),
),
);
}
}
class SecondPage extends StatelessWidget {
Widget build(BuildContext context) {
var bloc = BlocProvider.of<MyForm>(context);
return Scaffold(
body: Center(
child: RaisedButton(
onPressed: () {
bloc.add(SecondPageSubmitEvent(
inputC: 'text3',
inputD: 'text4',
));
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ThirdPage()),
);
},
child: Text('page 3'),
),
),
);
}
}
class ThirdPage extends StatelessWidget {
Widget build(BuildContext context) {
var bloc = BlocProvider.of<MyForm>(context);
return Scaffold(
body: Center(
child: RaisedButton(
onPressed: () {
bloc.add(ThirdPageSubmitEvent(
inputE: 'text5',
inputF: 'text6',
));
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => HomePage()),
(r) => r == null,
);
},
child: Text('page 3'),
),
),
);
}
}
class MyForm extends Bloc<MyFormEvent, MyFromState> {
MyForm() : super(MyFromState.empty);
@override
Stream<MyFromState> mapEventToState(MyFormEvent event) async* {
if (event is FirstPageSubmitEvent) {
yield (state.copyWith(
inputA: event.inputA,
inputB: event.inputB,
));
} else if (event is SecondPageSubmitEvent) {
yield (state.copyWith(
inputC: event.inputC,
inputD: event.inputD,
));
} else if (event is ThirdPageSubmitEvent) {
yield (state.copyWith(
inputE: event.inputE,
inputF: event.inputF,
));
}
}
}
abstract class MyFormEvent extends Equatable {}
class FirstPageSubmitEvent extends MyFormEvent {
FirstPageSubmitEvent({this.inputA, this.inputB});
final String inputA;
final String inputB;
@override
List<Object> get props => [inputA, inputB];
}
class SecondPageSubmitEvent extends MyFormEvent {
SecondPageSubmitEvent({this.inputC, this.inputD});
final String inputC;
final String inputD;
@override
List<Object> get props => [inputC, inputD];
}
class ThirdPageSubmitEvent extends MyFormEvent {
ThirdPageSubmitEvent({this.inputE, this.inputF});
final String inputE;
final String inputF;
@override
List<Object> get props => [inputE, inputF];
}
class MyFromState extends Equatable {
final String inputA;
final String inputB;
final String inputC;
final String inputD;
final String inputE;
final String inputF;
const MyFromState({
this.inputA,
this.inputB,
this.inputC,
this.inputD,
this.inputE,
this.inputF,
});
static const empty = MyFromState(
inputA: '',
inputB: '',
inputC: '',
inputD: '',
inputE: '',
inputF: '',
);
MyFromState copyWith({
String inputA,
String inputB,
String inputC,
String inputD,
String inputE,
String inputF,
}) {
return MyFromState(
inputA: inputA ?? this.inputA,
inputB: inputB ?? this.inputB,
inputC: inputC ?? this.inputC,
inputD: inputD ?? this.inputD,
inputE: inputE ?? this.inputE,
inputF: inputF ?? this.inputF,
);
}
@override
List<Object> get props => [inputA, inputB, inputC, inputD, inputE, inputF];
}
我有一个 单一表单 ,它根据用户体验和 UI 设计要求分为 3 个页面。结构如下所示:
MyApp
|
|- BlocProvider.of<MyBloc>(context)
|- PageA
| |- FormA
| |- InputA
| |- InputB
| |- InputC
| |- RaisedButton (Next button)
|
|- PageB
| |- FormA
| |- InputD
| |- InputE
| |- InputF
| |- RaisedButton (Back button)
| |- RaisedButton (Next button)
|
|- PageC
| |- FormA
| |- InputG
| |- InputH
| |- InputI
| |- RaisedButton (Back button)
| |- RaisedButton (Submit button)
我想传递相同的状态,并更新 RaisedButton
按钮的状态数据 onPressed
,而不用将我的树 包裹在 blocbuilder, bloclistener
或 blocconsumer
因为没有像在需要状态更改时重建小部件这样的事情。
我该怎么做?
NOTE
- Each form is a page, not a tabbar or pageview.
- I want only 1 bloc and 1 state to be shared across the page, not 1 bloc per page.
- I want this behavior simply because I'm actually avoid passing data from the constructor.
- Already tried
BlocProvider.of<MyBloc>(context).state
but it is not giving me access to the object.
我做了一个非常简单的例子希望对你有帮助。
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (_) => MyForm(),
child: MaterialApp(
title: 'Flutter Demo',
home: HomePage(),
),
);
}
}
class HomePage extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
BlocBuilder<MyForm, MyFromState>(
builder: (_, state) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('inputA: ${state.inputA}'),
Text('inputB: ${state.inputB}'),
Text('inputC: ${state.inputC}'),
Text('inputD: ${state.inputD}'),
Text('inputE: ${state.inputE}'),
Text('inputF: ${state.inputF}'),
],
);
},
),
Center(
child: RaisedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => FirstPage()),
);
},
child: Text('start'),
),
),
],
),
);
}
}
class FirstPage extends StatelessWidget {
Widget build(BuildContext context) {
var bloc = BlocProvider.of<MyForm>(context);
return Scaffold(
body: Center(
child: RaisedButton(
onPressed: () {
bloc.add(FirstPageSubmitEvent(
inputA: 'text1',
inputB: 'text2',
));
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondPage()),
);
},
child: Text('page 2'),
),
),
);
}
}
class SecondPage extends StatelessWidget {
Widget build(BuildContext context) {
var bloc = BlocProvider.of<MyForm>(context);
return Scaffold(
body: Center(
child: RaisedButton(
onPressed: () {
bloc.add(SecondPageSubmitEvent(
inputC: 'text3',
inputD: 'text4',
));
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ThirdPage()),
);
},
child: Text('page 3'),
),
),
);
}
}
class ThirdPage extends StatelessWidget {
Widget build(BuildContext context) {
var bloc = BlocProvider.of<MyForm>(context);
return Scaffold(
body: Center(
child: RaisedButton(
onPressed: () {
bloc.add(ThirdPageSubmitEvent(
inputE: 'text5',
inputF: 'text6',
));
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => HomePage()),
(r) => r == null,
);
},
child: Text('page 3'),
),
),
);
}
}
class MyForm extends Bloc<MyFormEvent, MyFromState> {
MyForm() : super(MyFromState.empty);
@override
Stream<MyFromState> mapEventToState(MyFormEvent event) async* {
if (event is FirstPageSubmitEvent) {
yield (state.copyWith(
inputA: event.inputA,
inputB: event.inputB,
));
} else if (event is SecondPageSubmitEvent) {
yield (state.copyWith(
inputC: event.inputC,
inputD: event.inputD,
));
} else if (event is ThirdPageSubmitEvent) {
yield (state.copyWith(
inputE: event.inputE,
inputF: event.inputF,
));
}
}
}
abstract class MyFormEvent extends Equatable {}
class FirstPageSubmitEvent extends MyFormEvent {
FirstPageSubmitEvent({this.inputA, this.inputB});
final String inputA;
final String inputB;
@override
List<Object> get props => [inputA, inputB];
}
class SecondPageSubmitEvent extends MyFormEvent {
SecondPageSubmitEvent({this.inputC, this.inputD});
final String inputC;
final String inputD;
@override
List<Object> get props => [inputC, inputD];
}
class ThirdPageSubmitEvent extends MyFormEvent {
ThirdPageSubmitEvent({this.inputE, this.inputF});
final String inputE;
final String inputF;
@override
List<Object> get props => [inputE, inputF];
}
class MyFromState extends Equatable {
final String inputA;
final String inputB;
final String inputC;
final String inputD;
final String inputE;
final String inputF;
const MyFromState({
this.inputA,
this.inputB,
this.inputC,
this.inputD,
this.inputE,
this.inputF,
});
static const empty = MyFromState(
inputA: '',
inputB: '',
inputC: '',
inputD: '',
inputE: '',
inputF: '',
);
MyFromState copyWith({
String inputA,
String inputB,
String inputC,
String inputD,
String inputE,
String inputF,
}) {
return MyFromState(
inputA: inputA ?? this.inputA,
inputB: inputB ?? this.inputB,
inputC: inputC ?? this.inputC,
inputD: inputD ?? this.inputD,
inputE: inputE ?? this.inputE,
inputF: inputF ?? this.inputF,
);
}
@override
List<Object> get props => [inputA, inputB, inputC, inputD, inputE, inputF];
}