为什么Flutter中的BloCListener无法保存状态,并且在身份验证期间存在setState问题?

问题描述

我正在使用Chopper和BLoC系统在Flutter应用上实现登录身份验证。我的完整代码here。 LoginForm中的BlocListner运作良好,可以在身份验证后将我导航到主页,但是存在两个问题:

  1. 当我在模拟器上终止该应用程序并重新启动时,它不记得登录状态,因此用户将不得不再次登录
  2. 在验证用户身份后,导航过程中将出现2秒钟的错误

问题1: 这是我要的main.dart:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  setupLocator();
  runApp(MultiBlocProvider(providers: [
    BlocProvider(create: (BuildContext context) {
      return dispatchBloc();
    }),BlocProvider(create: (BuildContext context) {
      return HistoryBloc();
    }),BlocProvider(create: (BuildContext context) {
      return LoginBloc();
    }),],child: MyApp()));
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  LoginBloc loginBloc;
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'dispatch Executive App',theme: ThemeData(
          primarySwatch: Colors.green,textTheme: Theme.of(context).textTheme.apply(
                fontSizeDelta: 1.5,)),//         home: LoginPage(),routes: {
        '/': (context) {
          return BlocListener<LoginBloc,LoginState>(
            cubit: loginBloc,listener: (BuildContext context,state) {},child: BlocBuilder<LoginBloc,LoginState>(
              builder: (BuildContext context,LoginState state) {
                if (state is LoadedLoginState) {
                  print("loaded log in from home!");
                  return Home(token: state.login.token);
                } else {
                  print(state);
                  return LoginPage();
                }
                //return Home();
              },),);
        },'/home': (context) => Home(),},//     home: LoginPage(),//change this for testing
    );
  }

问题2: 身份验证成功并且导航器进入主页后,This issue 显示2秒钟 这就是我用于登录表单的内容。 BlocListener和BlocBuilder在这里工作正常!

BlocBuilder(
                  cubit: loginBloc,builder: (context,state) {
                    if (state is LoadingLoginState) {
                      return Center(
                        child: CircularProgressIndicator(),);
                    }
                    if (state is LoadedLoginState) {
                      print(state);
                      print("in login form");
                      print(state.login.token);
                      Navigator.pushReplacementNamed(context,'/home');

                      return Text("Success " + state.login.token);
                    }
                    if (state is ErrorLoginState) {
                      return Text("Error" + state.error);
                    } else {
                      return SizedBox(width: 20.0);
                    }
                  },

请帮助!非常感谢。

解决方法

对于第一个问题,您应该将密钥保存在手机内存中。为此,您可以使用来自flutter的shared_preferences包。

这里是例子。

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'SharedPreferences Demo',home: SharedPreferencesDemo(),);
  }
}

class SharedPreferencesDemo extends StatefulWidget {
  SharedPreferencesDemo({Key key}) : super(key: key);

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

class SharedPreferencesDemoState extends State<SharedPreferencesDemo> {
  Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
  Future<int> _counter;

  Future<void> _incrementCounter() async {
    final SharedPreferences prefs = await _prefs;
    final int counter = (prefs.getInt('counter') ?? 0) + 1;

    setState(() {
      _counter = prefs.setInt("counter",counter).then((bool success) {
        return counter;
      });
    });
  }

  @override
  void initState() {
    super.initState();
    _counter = _prefs.then((SharedPreferences prefs) {
      return (prefs.getInt('counter') ?? 0);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("SharedPreferences Demo"),),body: Center(
          child: FutureBuilder<int>(
              future: _counter,builder: (BuildContext context,AsyncSnapshot<int> snapshot) {
                switch (snapshot.connectionState) {
                  case ConnectionState.waiting:
                    return const CircularProgressIndicator();
                  default:
                    if (snapshot.hasError) {
                      return Text('Error: ${snapshot.error}');
                    } else {
                      return Text(
                        'Button tapped ${snapshot.data} time${snapshot.data == 1 ? '' : 's'}.\n\n'
                        'This should persist across restarts.',);
                    }
                }
              })),floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,tooltip: 'Increment',child: const Icon(Icons.add),);
  }
}

第二期,