我正在使用Firebase登录构建Flutter应用程序,但是在检查登录状态时遇到问题。在启动应用程序时,必须检查用户是否登录,以便可以显示正确的页面。如果登录显示首页(针对不同的用户角色)。如果没有,请显示登录页面。
我为此在应用程序的RootPage中使用streambuilder,但问题是应用程序必须首先通过Firestore db检查用户信息,以便它知道已登录的用户类型,然后才能路由至正确的页面。问题是我找不到让streambuilder在继续之前等待此功能检查用户信息的方法。因此,对由函数返回的值进行运算的条件不能正确评估。这是代码:
body: new StreamBuilder<FirebaseUser>(
stream: _auth.onAuthStateChanged,
builder: (BuildContext context, snapshot)
{
if (snapshot.connectionState == ConnectionState.waiting) {
return new SplashScreen();
}
if (snapshot.hasData && getUserDetailsComplete == true) {
_getUserDetails();
if (isAdmin == true) {
return new AdminScreen();
} else if (isAdmin == false) {
return new HomeScreen();
}
} else {
return new RootPage();
}
},
),
);
}
您现在可以通过以下方法解决此问题:1.在else语句中返回RootPage,使其循环执行,直到满足条件之一为止; 2.在函数_getUserDetails完成时将boolean设置为true,然后将其添加到条件中,以便小部件知道何时函数完成了。但这会使应用启动速度变慢,而且风格也不佳。
有人知道更好的方法吗?
谢谢大家!
答案 0 :(得分:0)
您可以使用StatefulWidget。在窗口小部件的状态下,包括一个窗口小部件对象。在initState
中,您可以存储一个占位符小部件(CircularProgressINnc等),然后调用一个在Firebase中进行某些检查的函数。确保此功能为async
,因为它进行网络连接,这必须在单独的线程上完成。在此函数的最后,只需调用setState并将占位符小部件替换为所选的小部件。看起来像这样:
class MyScreen extends StatefulWidget {
@override
_MyScreenState createState() => _MyScreenState();
}
class _MyScreenState extends State<MyScreen> {
Widget _screen;
@override
void initState() {
_screen = CircularProgressIndicator();
_doSomeFirebaseChecking();
}
void _doSomeFirebaseChecking() async {
// Add your code that performs checks at Firebase here.
// Then use setState to update the widget to a screen of choice.
setState(() {
if (isAdmin == true) {
_screen = AdminScreen();
} else if (isAdmin == false) {
_screen = HomeScreen();
}
});
}
}
在我编写的类似应用程序中,我不得不基于某些Web API的内容在屏幕上构建小部件。我使用了与此类似的方法,它的工作原理就像一种魅力。
我希望这会有所帮助!
答案 1 :(得分:0)
您可以使用 .then 和 .getIdToken 来获取令牌和声明中的用户详细信息
Map<dynamic, dynamic> claims = {};
Auth.onAuthStateChanged.map((firebaseUser) {
firebaseUser
.getIdToken()
.then((idTokenResult) => {
if (idTokenResult.claims != null)
{claims = idTokenResult.claims}
})
.catchError((e) => {print(e)});
有关使用自定义声明进行访问控制的更多信息:firebase Doc