flutter - 当我使用 pushNamedAndRemoveUntil() 时应用程序崩溃
问题描述
我正在完成我的应用程序的登录和注册屏幕的最后一点,但是当我使用退格键将用户从仪表板中注销时遇到了错误。
这实际上是非常情境化的。如果我要...
- 从主菜单页面开始
- 登入
pushnamedandRemoveUntil
当用户按下手机上的返回键时,从仪表板注销- 重复步骤 1-3
...然后一切正常。但是如果我按下主菜单上的返回键(这会导致应用程序进入睡眠状态,因为没有可以返回的屏幕),在我的手机上重新打开应用程序,然后重复步骤 1-3,那么我会得到一个错误说
The following RangeError was thrown while handling a gesture:
RangeError (index): Invalid value: Valid value range is empty: -1
除了错误代码所说的内容之外,我不确定如何解决该问题。
主要飞镖:
String host = Platform.environment['MONGO_DART_DRIVER_HOST'] ?? '127.0.0.1';
// String port = Platform.environment['MONGO_DART_DRIVER_PORT'] ?? '27017';
var port = 4000;
void main() async{
test();
runApp(juice_fit_life());
// var db = Db('mongodb://192.168.1.1:27017/juicefit');
// await db.open();
// print('Connected to Database');
}
class juice_fit_life extends StatelessWidget{
@override
Widget build(BuildContext context) {
var routes = {
Start.id:(context) => Start(),
SignIn.id: (context) => SignIn(),
SignUp.id:(context) => SignUp(),
MemberSignUp.id:(context)=>MemberSignUp(),
MemberSignUpGoals.id:(context)=>MemberSignUpGoals(),
MemberEndUserLicense.id:(context)=>MemberEndUserLicense(),
TrainerSignUp.id:(context) => TrainerSignUp(),
TrainerEndUserLicense.id:(context) => TrainerEndUserLicense(),
UserMainMenu.id:(context) => UserMainMenu(),
PlanInfo.id:(context) => PlanInfo(),
TrainerMainMenu.id:(context) => TrainerMainMenu()
};
return MultiProvider(
providers: [ChangeNotifierProvider<GoalData>(create: (_) => GoalData()),
ChangeNotifierProvider<StudentSignUpData>(create: (_) => StudentSignUpData()),
ChangeNotifierProvider<TrainerSignUpData>(create: (_) => TrainerSignUpData()),
ChangeNotifierProvider<PlanData>(create: (_) => PlanData()),
ChangeNotifierProvider<SignInData>(create: (_)=> SignInData())],
child: MaterialApp(
initialRoute:Start.id ,
onGenerateRoute: (settings){
WidgetBuilder builder;
Map arguments = settings.arguments;
if ( settings.name == PlanInfo.id){
builder = (context,)=> PlanInfo(
name:arguments["name"],
author: arguments["auth"],
intropar: arguments["intro"],
authorinfo: arguments['authInfo'],
comments:arguments['comments'],
authpic: arguments['picture']);
}
else{
builder = (context,) => routes[settings.name](context);
}
return CustomPageRoute(builder: builder, settings: settings);
// return PageRouteBuilder(pageBuilder: (context, animation1, animation2)=>routes[settings.name](context),
// transitionDuration: Duration(seconds: 0)
// );
},
),
);
}
}
Future<http.Response> test() {
return http.get('http://192.168.1.4:3000/');
登录.dart:
class SignIn extends StatefulWidget{
static String id = 'signIn';
@override
_SignIn createState()=> _SignIn();
}
class _SignIn extends State<SignIn>{
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
leading:IconButton(
icon: Icon(Icons.arrow_back_ios),
onPressed: (){
Navigator.pop(context);
},
),
backgroundColor: Colors.transparent,
elevation: 0.0,
),
body: Consumer<SignInData>(
builder: (context,data,child){
return ListView(
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(horizontal: 24.0),
child: Center(
child: Column(
children: <Widget>[
SizedBox(
height: 300.0,
),
TextField(
onChanged: (String value){
data.name = value;
},
decoration: InputDecoration(focusedBorder:new UnderlineInputBorder(borderSide: new BorderSide(color: Colors.white,width: 3.0)) ,enabledBorder: new UnderlineInputBorder(borderSide: new BorderSide(color: Colors.white,width: 3.0)),hintText: 'User Name',hintStyle: TextStyle(color: Colors.white) ),
style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold),
),
TextField(
obscureText: true,
enableSuggestions: false,
autocorrect: false,
onChanged: (String value){
data.password = value;
},
decoration: InputDecoration(focusedBorder:new UnderlineInputBorder(borderSide: new BorderSide(color: Colors.white,width: 3.0)) ,enabledBorder: new UnderlineInputBorder(borderSide: new BorderSide(color: Colors.white,width: 3.0)),hintText: 'Password',hintStyle: TextStyle(color: Colors.white) ),
style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold),
),
SizedBox(
height: 20.0,
),
Row(
children: [
Container(
child: data.badinput == false ? Text("Wrong User or Password",style: TextStyle(color: Colors.red,fontWeight: FontWeight.bold,fontSize: 15.0)):SizedBox()
),
],
),
SquareButton(
color:Colors.white,
pressed: () async{
hasher hash = new hasher();
print(hash.hashpass(data.password).toString());
final text = await data.checkUser(data.name,hash.hashpass(data.password).toString());
if(text == false){
print("result${text}");
data.badinput = false;
}
else{
if(text["userType"] == "trainer"){
Provider.of<TrainerSignUpData>(context, listen: false).trainerData.userName = data.name;
if (text["eulaAccept"] == false){
Navigator.pushNamedAndRemoveUntil(context, TrainerEndUserLicense.id,(r)=>false);
}
else{
Navigator.pushNamedAndRemoveUntil(context, TrainerMainMenu.id,(r)=>false);
}
}
else{
Provider.of<StudentSignUpData>(context, listen: false).studentData.userName = data.name;
if (text["eulaAccept"] == false){
Navigator.pushNamedAndRemoveUntil(context, MemberEndUserLicense.id,(r)=>false);
}
else{
Navigator.pushNamedAndRemoveUntil(context, UserMainMenu.id,(r)=>false);
}
}
print("result: ${text["eulaAccept"]}");
// Navigator.pushNamed(context, UserMainMenu.id);
}
data.notifyListeners();
},
butContent: Text('Sign In', style: TextStyle(color:Colors.black)),
buttonwidth:150.0
),
],
)
),
),
],
);
},
),
);
}
}
User_Main_Menu.dart:
class UserMainMenu extends StatefulWidget {
static String id = "UserMainMenu";
_UserMainMenu createState() => _UserMainMenu();
}
class _UserMainMenu extends State<UserMainMenu> {
int currentpage = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xffE5DDDD),
appBar: AppBar(
title: Text("Dashboard"),
backgroundColor: Color(0xff32416F),
leading: IconButton(
icon: Icon(Icons.menu),
onPressed: () {},
),
),
body: WillPopScope(
onWillPop: (){
var baseDialog = CustomAlertBox(
infolist: <Widget>[
Text(
"Do you want to sign out and close the app?"),
],
actionlist: <Widget>[
FlatButton(
child: Text("Yes"),
onPressed: () {
SchedulerBinding.instance.addPostFrameCallback((_) {
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (context) => Start()
),
ModalRoute.withName(Start.id)
);
});
// Provider.of<TrainerSignUpData>(context,listen: false).resetData();
},
),
FlatButton(
child: Text("No"),
onPressed: () {
Navigator.of(context, rootNavigator: true).pop(
false);
},
)
],
);
return showDialog(context: context, builder: (BuildContext context) => baseDialog);
},
child: SafeArea(
child: Consumer<PlanData>(builder: (context, data, child) {
if(currentpage == 0){
return Center(
child: Padding(
padding: EdgeInsets.only(left: 24.0, right: 24.0),
child: new ListView.builder(
itemCount: data.plans.length,
itemBuilder: (BuildContext context, int index) {
return Column(
children: [
PlanBanner(
name:data.plans[index]["name"],
author:data.plans[index]["author"],
img: data.plans[index]["picture"],
pressed: (){
// Navigator.push(
// context,
// MaterialPageRoute( builder: (context) => PlanInfo(),
// settings: RouteSettings(
// arguments: {"name": data.plans[index]["name"]}
// ))
// );
Navigator.of(context).pushNamed(PlanInfo.id,arguments:{
"data":data.plans[index]["name"],
"auth":data.plans[index]["author"],
"intro":"",
"authInfo":"",
"comments":"",
"picture": ""
});
print(index);
},
),
SizedBox(
height: 20.0,
)
],
);
})),
);
}
else{
return Center(
child: Padding(
padding: EdgeInsets.only(left: 24.0, right: 24.0),
child: new ListView.builder(
itemCount: data.plans.length,
itemBuilder: (BuildContext context, int index) {
return Column(
children: [
PlanBanner(
name:data.plans[index]["name"],
author:data.plans[index]["author"],
img: data.plans[index]["picture"],
pressed: (){
print(index);
}
),
SizedBox(
height: 20.0,
)
],
);
})),
);
}
}),
),
),
bottomNavigationBar: BottomAppBar(
child: Row(
children: [
Expanded(
child: Material(
elevation: 0.0,
color: currentpage == 0 ? Color(0xff32416F) : Colors.black,
child: MaterialButton(
child: Text(
"Available Plans",
style: TextStyle(color: Colors.white),
),
onPressed: () {
setState(() {
currentpage = 0;
});
},
),
),
),
Expanded(
child: Material(
elevation: 0.0,
color: currentpage == 1 ? Color(0xff32416F) : Colors.black,
child: MaterialButton(
child: Text("My Plans", style: TextStyle(color: Colors.white)),
onPressed: () {
setState(() {
currentpage = 1;
});
},
),
),
),
],
)),
);
}
}
解决方案
我认为解决此问题的最佳方法是使用Navigator.of(context).pushReplacement()
从登录屏幕到仪表板/主屏幕,因为当您这样做时,您将替换主屏幕的堆栈的第一条路由(即登录)以及何时你按下后退按钮,你只需要这样做Navigator.pop(context)
,它会关闭应用程序。同样的事情也适用于注销,您可以Navigator.of(context).pushReplacement()
再次使用登录屏幕。
推荐阅读
- c - 为什么在嵌入式 c 中输入大小写绝对内存地址?
- pandas - 如何使用正则表达式在熊猫数据框中选择包含特定子字符串的行之后的一行和固定数量的行
- react-native - 如何在 React Native 中使用预先填充的 Realm 数据库?
- html - Index.html 中的 JSON 文件
- android - 以编程方式打开连接的 Wifi 设置 Android 10
- c# - 串口在 Form3 中关闭?
- python - 如果值大于,如何插入行和插值
- rxjs - 订阅导入有什么区别
- php - 如何检查 PHP 中是否绕过了客户端输入验证?
- bash - 命令行中的 API 网关和 Lambda 函数