Flutter ลบทุกเส้นทาง


98

ฉันต้องการพัฒนาปุ่มออกจากระบบที่จะส่งฉันไปยังเส้นทางการเข้าสู่ระบบและลบเส้นทางอื่น ๆ ทั้งหมดออกจากไฟล์Navigator. เอกสารประกอบไม่ได้อธิบายวิธีสร้างRoutePredicateหรือมีฟังก์ชัน removeAll ประเภทใด ๆ

คำตอบ:


265

ฉันสามารถทำสิ่งนี้ได้ด้วยรหัสต่อไปนี้:

Navigator.of(context)
    .pushNamedAndRemoveUntil('/login', (Route<dynamic> route) => false);

ความลับที่นี่คือการใช้ RoutePredicate ที่ส่งคืนเท็จ(Route<dynamic> route) => falseเสมอ ในสถานการณ์นี้จะลบเส้นทางทั้งหมดยกเว้นเส้นทางใหม่ที่/loginฉันผลักดัน


1
ขอบคุณมากที่ทำงานได้สำเร็จ คุณช่วยกรุณาส่งลิงค์มาให้ฉันเพื่อที่จะได้เข้าใจมากขึ้น ....
Pawan

ฉันมีปัญหากับสิ่งนี้! บน iOS โดยใช้มุมมองเนทีฟเป็นวิดเจ็ตหลังจากใช้วิธีการของคุณแล้วมุมมองดั้งเดิมจะไม่ถูกกำจัดอย่างถูกต้องและยังคงมีอยู่ต่อไปด้วยเหตุนี้ฉันจึงมีมุมมองที่จะไม่ถูกใช้อีกต่อไปโดยทำงานในพื้นหลังและเป็นไปไม่ได้ที่จะทิ้ง . สิ่งนี้ดูเหมือนจะเกิดขึ้นบนอุปกรณ์ iOS เท่านั้น
Lorenzo Imperatrice

@LorenzoImperatrice คุณพบวิธีแก้ไขปัญหานี้หรือไม่? ฉันมีปัญหาคล้ายกัน
Mateusz Tylman

3
ฉันยังคงเปิดอินสแตนซ์อยู่แม้ว่าจะใช้สิ่งนี้แล้วก็ตาม วิธีอื่นใดในการดันหน้าจอและลบสแต็กที่เหลือ?
Manoj MM

เราจะส่งผ่านข้อโต้แย้งด้วยแนวทางนี้ได้อย่างไร
Developine

78

ฉันสามารถทำได้โดยใช้ข้อมูลโค้ดต่อไปนี้:

 Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) =>
    LoginScreen()), (Route<dynamic> route) => false),

ถ้าคุณต้องการที่จะลบทุกเส้นทางด้านล่างเส้นทางผลัก, RoutePredicateเสมอกลับเท็จเช่น(เส้นทางเส้นทาง) => เท็จ


24

อีกทางเลือกหนึ่งคือ popUntil()

Navigator.of(context).popUntil(ModalRoute.withName('/root'));

การดำเนินการนี้จะปิดเส้นทางทั้งหมดจนกว่าคุณจะกลับมาที่เส้นทางที่ระบุไว้


1
ฉันชอบคำตอบนี้มากกว่า!
พฤศจิกายน


10

ในกรณีที่คุณต้องการกลับไปที่หน้าจอนั้นและคุณไม่ได้ใช้เราเตอร์ที่มีชื่อสามารถใช้แนวทางถัดไปได้

ตัวอย่าง:

Navigator.pushAndRemoveUntil(context,
                  MaterialPageRoute(builder: (BuildContext context) => SingleShowPage()),
                  (Route<dynamic> route) => route is HomePage
              );

ด้วยเส้นทางคือ HomePageคุณตรวจสอบชื่อวิดเจ็ตของคุณ


NoAnimateRoute คืออะไร? ไม่พบคลาสที่มีชื่อเช่นนี้ใน Flutter
kashlo

@kashlo อย่าไปสนใจ =) เพียงแค่การใช้งานของฉันสามารถใช้ MaterialPageRoute แทนได้ แต่ฉันแก้ไขคำตอบแล้วขอบคุณ
Volodymyr Bilovus

(เส้นทาง <dynamic> เส้นทาง) => route.isFirst) หากบางคนต้องการลบออกไปจนถึงเส้นทางแรก
Hussnain Haidar

4

หากคุณกำลังใช้ namedRoutes คุณสามารถทำได้โดย:

Navigator.pushNamedAndRemoveUntil(context, "/login", (Route<dynamic> route) => false);

โดยที่"/ login"คือเส้นทางที่คุณต้องการผลักดันบนกองเส้นทาง

โปรดทราบว่า:

คำสั่งนี้จะลบเส้นทางทั้งหมดในสแต็กและทำให้เส้นทางที่พุชเป็นรูท


3

ฉันไม่รู้ว่าทำไมไม่มีใครพูดถึงวิธีแก้ปัญหาโดยใช้SchedularBindingInstanceแม้ว่าจะสายไปหน่อยฉันคิดว่านี่จะเป็นวิธีที่ถูกต้องในการตอบแต่แรกที่นี่

    SchedulerBinding.instance.addPostFrameCallback((_) async {
                              Navigator.of(context).pushNamedAndRemoveUntil(
                                  '/login',
                                  (Route<dynamic> route) => false);
                            });

รหัสด้านบนจะลบเส้นทางและการนำทางทั้งหมดไปที่ '/ เข้าสู่ระบบ' สิ่งนี้ยังทำให้เกินกว่าที่เฟรมทั้งหมดจะแสดงผลก่อนที่จะนำทางไปยังเส้นทางใหม่โดยกำหนดเวลาการโทรกลับ


1

นี่ใช้งานได้สำหรับฉัน อันที่จริงฉันทำงานกับกลุ่มแต่ปัญหาของฉันคือกลุ่มหน้าจอเข้าสู่ระบบ ไม่ได้อัปเดตหลังจากออกจากระบบ มันถือข้อมูลรุ่นก่อนหน้า แม้ฉันป้อนรายการผิดมันกำลังไปที่หน้าจอหลัก

ขั้นตอนที่ 1:

Navigator.of(context).pushNamedAndRemoveUntil(
        UIData.initialRoute, (Route<dynamic> route) => false);

ที่ไหน UIData.initialRoute = "/" or "/login"

ขั้นตอนที่ 2:

กำลังรีเฟรชหน้าจอ หากคุณกำลังทำงานกับ Bloc มันจะมีประโยชน์มาก

runApp(MyApp());

ที่ไหน MyApp() is the root class.

ระดับราก (เช่นแอปของฉัน)รหัส

class MyApp extends StatelessWidget {

  final materialApp = Provider(
      child: MaterialApp(
          title: UIData.appName,
          theme: ThemeData(accentColor: UIColor().getAppbarColor(),
            fontFamily: UIData.quickFont,
          ),
          debugShowCheckedModeBanner: false,
          //home: SplashScreen(),
          initialRoute: UIData.initialRoute,
          routes: {
            UIData.initialRoute: (context) => SplashScreen(),
            UIData.loginRoute: (context) => LoginScreen(),
            UIData.homeRoute: (context) => HomeScreen(),
          },
          onUnknownRoute: (RouteSettings rs) => new MaterialPageRoute(
              builder: (context) => new NotFoundPage(
                appTitle: UIData.coming_soon,
                icon: FontAwesomeIcons.solidSmile,
                title: UIData.coming_soon,
                message: "Under Development",
                iconColor: Colors.green,
              )
          )));

  @override
  Widget build(BuildContext context) {
    return materialApp;
  }
}

void main() => runApp(MyApp());

นี่คือวิธีการออกจากระบบของฉัน

void logout() async {
    SharedPreferences preferences = await SharedPreferences.getInstance();
    preferences.clear();

    // TODO: we can use UIData.loginRoute instead of UIData.initialRoute
    Navigator.of(context).pushNamedAndRemoveUntil(
        UIData.initialRoute, (Route<dynamic> route) => false);
    //TODO: It's working as refresh the screen
    runApp(MyApp());
  }

0

ไม่แน่ใจว่าทำถูกไหม

แต่สิ่งนี้เหมาะกับการใช้งานของฉันในการ popping จนถึงโดยวิดเจ็ตรูท

void popUntilRoot({Object result}) {
    if (Navigator.of(context).canPop()) {
      pop();
      popUntilRoot();
    }
}

0
to clear route - 

  onTap: () {
                    //todo to clear route -
                    Navigator.of(context).pop();
                    Navigator.push(context, MaterialPageRoute(builder: (context) => UpdateEmployeeUpdateDateActivity(_token),));
                    widget.listener.onEmployeeDateClick(_day,_month, _year);
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.