当我注销应用时,我可以按后退按钮返回到注销前的最后一个页面。然而,奇怪的是,只有当我在登录时导航到主页以外的另一个页面时,才会出现此意外功能。
我使用Firebase来管理我的用户身份验证,我设置了一个类来管理身份验证,如下所示:
class AuthService {
// creating a member of class that represents an instance of firebase authentication
final FirebaseAuth _auth = FirebaseAuth.instance;
// create user object based on firebase User class
AppUser? _userFromFirebaseUser(User user) {
// ternary operator
return user != null ? AppUser(uid: user.uid) : null;
}
// auth change user stream
Stream<AppUser> get user {
// mapping firebase User to User
return _auth.authStateChanges().map((User? user) => _userFromFirebaseUser(user!)!);
}
}
// sign in with email & password
Future signIn(String email, String password) async {
try {
UserCredential result = await _auth.signInWithEmailAndPassword(email: email, password: password);
User? firebaseUser = result.user;
return _userFromFirebaseUser(firebaseUser!);
} catch(e) {
print(e.toString());
return null;
}
}
// register with email & password
Future registerWithEmailAndPassword(String email, String password) async {
try {
UserCredential result = await _auth.createUserWithEmailAndPassword(email: email, password: password);
User? firebaseUser = result.user;
return _userFromFirebaseUser(firebaseUser!);
} catch(e) {
print(e.toString());
return null;
}
}
// sign out
Future signOutFunc() async {
try {
_auth.signOut();
} catch(e) {
print('Failed to sign out');
print(e);
}
}
}
这个类不断地监听用户身份验证的变化,并根据用户是否登录显示登录或注册页面。
class Wrapper extends StatelessWidget {
const Wrapper({super.key});
@override
Widget build(BuildContext context) {
final user = Provider.of<AppUser?>(context);
print(user);
// return either HomePage or Athenticate Widget
// listening to auth changes from stream
if (user == null) {
return Authenticate();
} else {
return MyHomePage();
}
}
}
当用户注销时,此小部件将用户引导到注册页面。
class Authenticate extends StatefulWidget {
const Authenticate({super.key});
@override
State<Authenticate> createState() => _AuthenticateState();
}
class _AuthenticateState extends State<Authenticate> {
@override
Widget build(BuildContext context) {
return RegisterPage();
}
}
这是用户登录后我通常在应用中管理导航的方式:
class RouteGenerator {
// static function to generate route
static Route<dynamic> generateRoute(RouteSettings settings) {
// getting arguments passed in while callling Navigator.pushNamed()
final args = settings.arguments as Map<String, dynamic>?;
// checking if the name of the route is the home route
switch (settings.name) {
case '/':
return MaterialPageRoute(builder: (_) => MyHomePage());
case 'ReceiptExplorer':
return MaterialPageRoute(builder: (_) => ReceiptExplorer());
case 'SignInPage':
return MaterialPageRoute(builder: (_) => SignInPage());
case 'PicturePreviewPage':
final imagePath = args!['imagePath'] as String;
return MaterialPageRoute(
builder: (_) => PicturePreviewPage(imagePath: imagePath));
case 'RegisterPage':
return MaterialPageRoute(builder: (_) => RegisterPage());
default:
return _errorRoute();
}
}
}
Route<dynamic> _errorRoute() {
return MaterialPageRoute(builder: (_) {
return Scaffold(
appBar: AppBar(
title: Text("Error"),
),
body: Center(
child: Text('ERROR'),
));
});
}
这里是我的main.dart,我使用流提供程序向其子部件提供AppUser(一个自定义类,它抽象了检索firebase User时返回的所有不必要的信息)对象流。
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
// ignore: use_key_in_widget_constructors
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return StreamProvider<AppUser?>.value
( initialData: null,
catchError: (User, AppUser) => null,
value: AuthService().user,
child: const MaterialApp(
debugShowCheckedModeBanner: false,
home: Wrapper(),
initialRoute: "/",
onGenerateRoute: RouteGenerator.generateRoute,
),
);
}
}
我尝试在Authenticate Widget中返回SignInPage而不是RegisterPage,但这并没有改变任何东西。我还使用以下代码更新了Authenticate Widget,尝试用新页面替换Widget堆栈的顶部,但这也没有改变任何东西。
class Authenticate extends StatefulWidget {
const Authenticate({Key? key});
@override
State<Authenticate> createState() => _AuthenticateState();
}
class _AuthenticateState extends State<Authenticate> {
@override
void initState() {
super.initState();
WidgetsBinding.instance?.addPostFrameCallback((_) {
Navigator.of(context).pushReplacementNamed('SignInPage');
});
}
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}
}
我看到一些其他的帖子,人们用途:
Navigator.of(context).popUntil(ModalRoute.withName('/')); // pops the stack back to the home page
或
Navigator.of(context).pushNamedAndRemoveUntil('/', (route) => false)
...但我不确定如何实现这些,因为我的主页(/)路由是我的应用程序的主页,而不是登录或注册页面,所以这些方法只会在我注销应用程序时返回应用程序的主页,这是不可取的。
总而言之,我想知道为什么当我退出应用程序时屏幕上甚至会显示一个后退按钮,它会将我带到注册页面,以及为什么当我按下此后退按钮时,它会将我带到我登录时的图片预览页面。
下面是一个视频,可以更轻松地演示我的问题是什么:https://youtu.be/Kl4KOwRgHS0
2条答案
按热度按时间sxpgvts31#
从注册页面中删除后退按钮。
如果你需要显示它(如果你想从另一个页面导航到注册页面,通过使用Navigator.push(...)),然后使用(leading:)参数或AppBar手动添加它。
4xrmg8kj2#
我扩展了AuthenticateState小部件的initState函数,并使用了Navigator.pushNamedAndRemoveUntil(),它解决了我的问题。