android - 为什么 Flutter 中的 BloCListener 不保存状态,认证过程中出现 setState() 问题?
问题描述
我正在使用 Chopper 和 BLoC 系统在我的 Flutter 应用程序上实现登录身份验证。我的完整代码在这里。LoginForm 中的 BlocListner 运行良好,它可以在身份验证后将我导航到 HomePage,但有 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: 身份验证成功并且导航器指向主页后,此问题出现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);
}
},
),
请帮忙!太感谢了。
解决方案
对于第一个问题,您应该将密钥保存在手机内存中。为此,您可以使用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),
),
);
}
}
对于第二个问题,
推荐阅读
- html - "GET /media/img/image.png HTTP/1.1" 404 2575
- r - 跨多个变量复制分组函数以生成许多新变量
- r - Rmarkdown 不会将蒙特塞拉特字体编织为 PDF
- android - startActivity 在 Android 11 中引发异常
- java - Antlr4 - 获取令牌名称
- django - 为什么我的搜索栏在 Django 中不起作用?
- java - Dispather servlet 问题(上下文初始化失败)
- javascript - 使用 jquery 附加一个单选选项
- r - 使用全局变量作为 R 函数的输入
- python - python中的“重组”数据框