Flutter/dart:Parse Server sdk:ParseUser.currentUser() 函数在重置时返回 null
Posted
技术标签:
【中文标题】Flutter/dart:Parse Server sdk:ParseUser.currentUser() 函数在重置时返回 null【英文标题】:Flutter/dart: Parse Server sdk: ParseUser.currentUser() function returning null on reset 【发布时间】:2021-03-25 22:06:16 【问题描述】:我在我的颤振应用程序中使用“Parse Server sdk”和“back4app”作为后端,并且在使用以下函数调用当前用户时遇到问题:“ParseUser.currentUser()”但是出于某种原因,即使在我重新启动应用程序时登录后,该函数也会返回 null
pubspec.yaml
dependencies:
parse_server_sdk: ^2.1.0
Main.dart
void main() async
WidgetsFlutterBinding.ensureInitialized();
final keyApplicationId = 'xxxxxxxxx';
final keyParseServerUrl = 'https://parseapi.back4app.com';
final keyClientkey = 'xxxxxxxxxx';
await Parse().initialize(
keyApplicationId,
keyParseServerUrl,
clientKey: keyClientkey,
debug: true
);
print('connected to Parse Server');
runApp(MyApp());
class MyApp extends StatelessWidget
Future<bool> hasUserLogged() async
print('future called');
ParseUser currentUser = await ParseUser.currentUser() as ParseUser;
if (currentUser == null)
return false;
//Validates that the user's session token is valid
final ParseResponse parseResponse =
await ParseUser.getCurrentUserFromServer(
currentUser.get<String>('sessionToken'));
if (!parseResponse.success)
print('call failed');
//Invalid session. Logout
await currentUser.logout();
return false;
else
print('user found');
return true;
@override
Widget build(BuildContext context)
return MaterialApp(
title: 'Flutter - Parse Server',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: FutureBuilder<bool>(
future: hasUserLogged(),
builder: (context, snapshot)
switch (snapshot.connectionState)
case ConnectionState.none:
case ConnectionState.waiting:
return Scaffold(
body: Center(
child: Container(
width: 100,
height: 100,
child: CircularProgressIndicator()),
),
);
default:
if (snapshot.hasData && snapshot.data)
print('to User');
return UserPage();
else
print('to Login');
return LoginPage();
),
);
登录页面:
class LoginPage extends StatefulWidget
@override
_LoginPageState createState() => _LoginPageState();
class _LoginPageState extends State<LoginPage>
final controllerUsername = TextEditingController();
final controllerPassword = TextEditingController();
bool isLoggedIn = false;
@override
Widget build(BuildContext context)
return Scaffold(
appBar: AppBar(
title: const Text('Flutter - Parse Server'),
),
body: Center(
child: SingleChildScrollView(
padding: const EdgeInsets.all(8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
height: 200,
child: Image.network(
'https://blog.back4app.com/wp-content/uploads/2017/11/logo-b4a-1-768x175-1.png'),
),
Center(
child: const Text('Flutter on Back4App',
style:
TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
),
SizedBox(
height: 16,
),
TextField(
controller: controllerUsername,
enabled: !isLoggedIn,
keyboardType: TextInputType.text,
textCapitalization: TextCapitalization.none,
autocorrect: false,
decoration: InputDecoration(
border: OutlineInputBorder(
borderSide: BorderSide(color: Colors.black)),
labelText: 'Username'),
),
SizedBox(
height: 8,
),
TextField(
controller: controllerPassword,
enabled: !isLoggedIn,
obscureText: true,
keyboardType: TextInputType.text,
textCapitalization: TextCapitalization.none,
autocorrect: false,
decoration: InputDecoration(
border: OutlineInputBorder(
borderSide: BorderSide(color: Colors.black)),
labelText: 'Password'),
),
SizedBox(
height: 16,
),
Container(
height: 50,
child: ElevatedButton(
child: const Text('Login'),
onPressed: isLoggedIn ? null : () => doUserLogin(),
),
),
SizedBox(
height: 16,
),
Container(
height: 50,
child: ElevatedButton(
child: const Text('Sign Up'),
onPressed: () => navigateToSignUp(),
),
),
SizedBox(
height: 16,
),
Container(
height: 50,
child: ElevatedButton(
child: const Text('Reset Password'),
onPressed: () => navigateToResetPassword(),
),
)
],
),
),
));
void doUserLogin() async
final username = controllerUsername.text.trim();
final password = controllerPassword.text.trim();
final user = ParseUser(username, password, null);
var response = await user.login();
if (response.success)
navigateToUser();
else
Message.showError(context: context, message: response.error.message);
void navigateToUser()
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => UserPage()),
(Route<dynamic> route) => false,
);
void navigateToSignUp()
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SignUpPage()),
);
void navigateToResetPassword()
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ResetPasswordPage()),
);
主页:
class UserPage extends StatelessWidget
ParseUser currentUser;
Future<ParseUser> getUser() async
currentUser = await ParseUser.currentUser() as ParseUser;
return currentUser;
@override
Widget build(BuildContext context)
void doUserLogout() async
var response = await currentUser.logout();
if (response.success)
Message.showSuccess(
context: context,
message: 'User was successfully logout!',
onPressed: ()
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => LoginPage()),
(Route<dynamic> route) => false,
);
);
else
Message.showError(context: context, message: response.error.message);
return Scaffold(
appBar: AppBar(
title: Text('User logged in - Current User'),
),
body: FutureBuilder<ParseUser>(
future: getUser(),
builder: (context, snapshot)
switch (snapshot.connectionState)
case ConnectionState.none:
case ConnectionState.waiting:
return Center(
child: Container(
width: 100,
height: 100,
child: CircularProgressIndicator()),
);
break;
default:
return Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(child: Text('Hello, $snapshot.data.username')),
SizedBox(
height: 16,
),
Container(
height: 50,
child: ElevatedButton(
child: const Text('Logout'),
onPressed: () => doUserLogout(),
),
),
],
),
);
));
当使用应用程序登录工作正常,但当我重新加载应用程序时,它只是“MyApp”类中的“ParseServer.currentUser()”返回 null 并将我发送到登录屏幕。如果有人知道我做错了什么,我将不胜感激。
“MyApp”类中的 FutureBuilder 也两次调用 Future 我不知道为什么,如果这可能与它有关。
【问题讨论】:
【参考方案1】:对于主 Future 构建器的每个状态,下面的所有小部件都将重新创建,构建函数将被再次调用,并将再次调用 Future.Builder 中的函数。
您可以使用 AsyncMemoizer 来避免它。 AsyncMemoizer 将使 Future 只被调用一次。 你有很多方法可以解决这个问题。 例如,您可以使用 StatefullWidget 并在 initState() 上获取数据,它只会被调用一次,即使父级重建,状态也会保持。
最好的做法是创建其他层来获取您的数据,而您的视图只负责显示,而不是获取它。
https://pub.dev/packages/async
https://pub.dev/documentation/async/latest/async/AsyncMemoizer-class.html
【讨论】:
以上是关于Flutter/dart:Parse Server sdk:ParseUser.currentUser() 函数在重置时返回 null的主要内容,如果未能解决你的问题,请参考以下文章
在 Flutter(Dart)中将字符串解析为 DateTime [重复]