首页 > 解决方案 > 当我使用 pushNamedAndRemoveUntil() 时应用程序崩溃

问题描述

我正在完成我的应用程序的登录和注册屏幕的最后一点,但是当我使用退格键将用户从仪表板中注销时遇到了错误。

这实际上是非常情境化的。如果我要...

  1. 从主菜单页面开始
  2. 登入
  3. pushnamedandRemoveUntil当用户按下手机上的返回键时,从仪表板注销
  4. 重复步骤 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;
                  });
                },
              ),
            ),
          ),
        ],
      )),
    );
  }
}

标签: flutterdart

解决方案


我认为解决此问题的最佳方法是使用Navigator.of(context).pushReplacement()从登录屏幕到仪表板/主屏幕,因为当您这样做时,您将替换主屏幕的堆栈的第一条路由(即登录)以及何时你按下后退按钮,你只需要这样做Navigator.pop(context),它会关闭应用程序。同样的事情也适用于注销,您可以Navigator.of(context).pushReplacement()再次使用登录屏幕。


推荐阅读