Смена экранов с помощью блока - PullRequest
0 голосов
/ 10 ноября 2019

Я пытаюсь переключать экраны (виджеты без состояния) с помощью блока, при этом с помощью BlocBuilder для вывода различных виджетов в соответствии с состоянием контекст меняется на новый отображаемый виджет. слушатель состояния вызывается в новом виджете.

Мне удалось показать виджет, когда состояние изменилось, проблема в том, когда состояние снова меняется, затем контекст изменяется, и в виджете вызывается функция построителя. это было показано.

, поэтому я создал унаследованный виджет, который будет содержать блок, чтобы я мог отправить событие из подвиджета на родительский объект и затем показать другой виджет на основе состояния.

class SignupViewManager extends InheritedWidget {
  final SignupBloc bloc;
  final Widget child;

  SignupViewManager({Key key, this.child, this.bloc}) : super(key: key, child: child);

  static SignupViewManager of(BuildContext context) {
    return (context.inheritFromWidgetOfExactType(SignupViewManager) as SignupViewManager);
  }

  @override
  bool updateShouldNotify(SignupViewManager oldWidget) {
    return true;
  }
}

class SignupHomePage extends StatelessWidget {
  final SignupBloc signupBloc = SignupBloc();

  SignupHomePage({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return SignupViewManager(
        bloc: SignupBloc(),
        child: BlocProvider<SignupBloc>(
          builder: (context) => signupBloc,
          child: BlocBuilder<SignupBloc, SignupState>(
              builder: (context, state) => _signupBuilder(context, state),
              condition: (previousState, state) => _signupCondition(previousState, state),
        ),
      )
    );
  }

  Widget _signupBuilder(BuildContext context, SignupState state) {
    print("IN SIGNUP MAIN BUILDER $state");
    // Changing the UI based on the current state
    if (state is SignupInitial) { // Show credentials for initial state
      return SignupCredentials();
    } else if (state is SavedCredentials) { // Show Agreements after credentials has been saved.
      return SignupAgreements(user: state.user);
    }

    return Text("default");
  }
}

class SignupCredentials extends StatelessWidget {
  SignupBloc signupBloc;

  void _signup(email, password, confirmPassword) {
    if(password == confirmPassword) {
      signupBloc.add(SaveCredentials(email, password));
    } else {
      print("passwords do not match");
    }
  }

  Widget _bloc() {
    return BlocBuilder<SignupBloc, SignupState>(
        builder: (context, state) {
            print("IN SIGNUP credentials builder $state");

            if(state is SavedCredentials) {
            return SignupDetails();
            }

            return Text("${state.runtimeType}");
        },
    );
  }
}

Таким образом, когда для состояния установлено значение RegistrationInitial, должен появиться виджет состояния без регистрации RegistrationCredentials. и затем, когда пользователь вводит учетные данные и отправляет их, отправляется событие SavedCredentials, и должно появиться RegistrationAgreements. но происходит то, что построитель RegistrationCredentials получает новое состояние вместо RegistrationHomePage.

1 Ответ

0 голосов
/ 10 ноября 2019

Я решил это.

Я изменил провайдера блока, чтобы он был типа RegistrationBloc.

@override
  Widget build(BuildContext context) {
    return AuthenticationPageLayout(
      color: Colors.white,
      opacity: 0.05,
      child: SignupViewManager(
        child: BlocProvider<SignupBloc>(
            builder: (context) => SignupBloc(),
            child: BlocListener<SignupBloc, SignupState>(
                listener: (context, state) => _signupListener(context, state),
                condition: (previousState, state) => _signupCondition(previousState, state),
                child: BlocBuilder<SignupBloc, SignupState>(
                builder: (context, state) => _signupBuilder(context, state),
                condition: (previousState, state) => _signupCondition(previousState, state),
                )
            )
        );
      )
    );
  }

Затем я сослался на провайдера блока, используя эту строку

BlocProvider.of<SignupBloc>(context)
...