为啥 Flutter 中的 BloCListener 不保存状态,认证过程中出现 setState() 问题?
Posted
技术标签:
【中文标题】为啥 Flutter 中的 BloCListener 不保存状态,认证过程中出现 setState() 问题?【英文标题】:Why is BloCListener in Flutter not saving state, and there's a setState() issue during authentication?为什么 Flutter 中的 BloCListener 不保存状态,认证过程中出现 setState() 问题? 【发布时间】:2021-01-02 05:59:54 【问题描述】:我正在使用 Chopper 和 BLoC 系统在我的 Flutter 应用程序上实现登录身份验证。我的完整代码是here。 LoginForm 中的 BlocListner 效果很好,认证后可以导航到 HomePage,但是有两个问题:
-
当我在模拟器上终止应用并重新启动时,它不会记住登录状态,因此用户必须重新登录。
在用户通过身份验证后,在导航过程中会出现错误 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);
,
),
请帮忙!非常感谢。
【问题讨论】:
您想第二次自动进入,无需再次登录?这是你的需要吗? 第二点,我导航了几次,但没有收到任何错误。当您收到错误消息时? 【参考方案1】:对于第一个问题,您应该将密钥保存在手机内存中。为此,您可以使用来自 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),
),
);
关于第二期,
【讨论】:
以上是关于为啥 Flutter 中的 BloCListener 不保存状态,认证过程中出现 setState() 问题?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Flutter 中的 BloCListener 不保存状态,认证过程中出现 setState() 问题?
为啥我们在 Flutter/Dart 中的 catch 参数中加上“e”?
Flutter - DEBUG 中的 Webview 正在工作,但在 RELEASE apk 上显示为空白,为啥?