Избегать блокировки виджетов для setState в кнопке onPress? - PullRequest
0 голосов
/ 19 октября 2018

Я хочу реализовать простую систему входа / выхода с помощью firebase.Я успешно внедрил систему входа / выхода.При входе в систему пользователь будет перенаправлен на главный экран, а после выхода из системы пользователь будет перенаправлен на экран входа в систему (с помощью RootScreen для управления переходом на главную страницу или вход в систему).Затем я добавляю новую страницу SettingScreen и перемещаю процесс выхода на страницу настроек.Итак, процесс пользователя Войти -> Домашняя страница (открыть ящик) -> Настройка.Однако после этого процесс выхода из системы стал ошибкой на экране настройки и получил это сообщение

"еще одно исключение: setState () или markNeedsBuild () вызывается, когда дерево виджетов было заблокировано"

Как ни странно, нет проблем с кодом экрана настройки, если я непосредственно выполняю процесс входа / выхода из HomePage на экран настройки.

Коды (RootScreen & SettingScreen):

import 'package:flutter/material.dart';
import 'login_screen.dart';
import 'home_screen.dart';
import 'setting_screen.dart';
import '../utilities/auth.dart';

class RootScreen extends StatefulWidget {
  RootScreen({this.auth});
  final BaseAuth auth;

  @override
  State<StatefulWidget> createState() => new RootState();
}

enum AuthStatus { notSignedIn, signedIn }

class RootState extends State<RootScreen> {
  AuthStatus authStatus = AuthStatus.notSignedIn;

  @override
  void initState() {
    super.initState();
    widget.auth.currentUser().then((userId) {
      setState(() {
        authStatus =
            userId == null ? AuthStatus.notSignedIn : AuthStatus.signedIn;
      });
    });
  }

  void signedIn() {
    setState(() {
      authStatus = AuthStatus.signedIn;
    });
  }

  void signedOut() {
    setState(() {
      authStatus = AuthStatus.notSignedIn;
    });
  }

  @override
  Widget build(BuildContext context) {
    switch (authStatus) {
      case AuthStatus.notSignedIn:
        return new LoginScreen(auth: widget.auth, onSignedIn: signedIn);
      case AuthStatus.signedIn:
        return new HomeScreen(auth: widget.auth, onSignedOut: signedOut);
    }
  }
}

2. Setting Screen & State:

import 'dart:async';
import 'package:flutter/material.dart';
import '../utilities/auth.dart';

class SettingScreen extends StatefulWidget {
  SettingScreen({this.auth, this.onSignedOut});
  final BaseAuth auth;
  final VoidCallback onSignedOut;
  final String title = "Setting";

  @override
  SettingState createState() => SettingState();
}

class SettingState extends State<SettingScreen> {

  void signOut() async {
    setState(() {
      try {
        widget.auth.signOut();
        widget.onSignedOut();
      } catch (e) {
        print(e);
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Settings'),
        actions: <Widget>[
          new FlatButton(
            child: Text('Logout',
                style: new TextStyle(fontSize: 17.0, color: Colors.white)),
            onPressed: signOut,
          )
        ],
      ),
      body: new Container(
          child: new Center(
        child: new Text('Settings', style: new TextStyle(fontSize: 32.0)),
      )),
    );
  }
}

Домашний экран:

class HomeScreen extends StatefulWidget {
  HomeScreen({this.auth, this.onSignedOut});
  final BaseAuth auth;
  final VoidCallback onSignedOut;

  @override
  HomeState createState() => HomeState();

  void signOut() async {
    try {
      await auth.signOut();
      onSignedOut();
    } catch (e) {
      print(e);
    }
  }
}
//.. Inside the HomeState -> ListTile to Setting Menu
ListTile(
        title:
            Text('Pengaturan', style: new TextStyle(color: Colors.black)),
        onTap: () {
          // Update the state of the app
          // ...
          // Then close the drawer
          Navigator.push(
            context,
            MaterialPageRoute(
                builder: (context) => SettingScreen(
                    auth: widget.auth, onSignedOut: widget.onSignedOut)),
          );
        },
      ),
//..

Как избежать этого исключения setState и виджета для этого случая?

1 Ответ

0 голосов
/ 20 октября 2018

Спасибо, основываясь на комментариях Азизы, я решил проблему, добавив два Navigator.pop (context): первый в ящик перед тем, как перейти в другое меню, чтобы избежать блокировки виджетов, и второй в методе выхода, так что вернитесь в RootScreen..

Ящик исходного состояния:

//.. Inside the HomeState -> ListTile to Setting Menu
ListTile(
        title:
            Text('Pengaturan', style: new TextStyle(color: Colors.black)),
        onTap: () {
          // ...
          // Add this
          Navigator.pop(context);
          Navigator.push(
            context,
            MaterialPageRoute(
                builder: (context) => SettingScreen(
                    auth: widget.auth, onSignedOut: widget.onSignedOut)),
          );
        },
      ),
//..

Способ выхода из системы на экране настройки:

void signOut() async {
    setState(() {
      try {
        widget.auth.signOut();
        widget.onSignedOut();
        Navigator.pop(context);
      } catch (e) {
        print(e);
      }
    });
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...