使用一个集团,以页面分割形式的一种状态?

问题描述

我有一个单个表单,根据UX和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)

我想传递相同的状态,并更新onpressed按钮的状态数据RaisedButton,而不会将我的树包在blocbuilder,bloclistener或{{1 }},因为不需要像在状态更改时重建小部件之类的事情。

我该怎么做?

注意

  • 每个表单都是页面,而不是标签栏或综合浏览量。
  • 我只希望在整个页面上共享1个集团和1个状态,而不是每页1个集团。
  • 我想要这种行为仅仅是因为我实际上避免了从构造函数传递数据。
  • 已经尝试过blocconsumer,但它没有使我能够访问该对象。

screenshot of IDE autocompletion

解决方法

我已经举了一个非常简单的例子,希望对您有所帮助。

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',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,);
  }
}

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];
}