フラッターはすべてのルートを削除します


106

ログインルートに移動し、から他のすべてのルートを削除するログアウトボタンを開発したいと思いますNavigator。ドキュメントには、RoutePredicateまたは任意の種類のremoveAll関数の作成方法が説明されていないようです。

回答:


275

私は次のコードでこれを達成することができました:

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

ここでの秘密は、常にfalseを返すRoutePredicateを使用すること(Route<dynamic> route) => falseです。この状況では、/loginプッシュした新しいルートを除くすべてのルートが削除されます。


1
どうもありがとうございました。あなたは....私はもっと理解することができますいくつかのリンクを送ってもらえ
Pawan

これで問題が発生しました!iOSでは、ウィジェットとしてネイティブビューを使用することにより、メソッドを使用した後、ネイティブビューが適切に破棄されず、存在し続けます。その結果、ある種のバックグラウンドで実行されて破棄できないビューがあります。 。これはiOSデバイスでのみ発生するようです。
LorenzoImperatrice19年

@LorenzoImperatriceこの問題の修正は見つかりましたか?私は同様の問題を抱えています
MateuszTylman19年

3
これを使用した後でも、インスタンスは開いたままです。画面を押してスタックの残りを削除する他の解決策はありますか?
manojMM19年

このアプローチでどのように引数を渡すことができますか。
開発

84

私は次のコードスニペットで行うことができます:

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

プッシュされたルートの下にあるすべてのルートを削除する場合、RoutePredicateは常にfalseを返します(例:(Route route)=> false)


27

別の選択肢は popUntil()

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

これにより、指定されたルートに戻るまで、すべてのルートがポップオフされます。


1
私はこの答えが好きです!
小説


11

特定の画面に戻りたいが、名前付きルーターを使用しない場合は、次のアプローチを使用できます

例:

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

ホームページのルートである、あなたのウィジェットの名前を確認してください。


NoAnimatedRouteとは何ですか?フラッターで、このような名前を持つクラスを見つけるカント
kashlo

@kashlo注意を払わないでください=)私の実装だけが代わりにMaterialPageRouteを使用できます。しかし、私は答えを編集しました、ありがとう。
VolodymyrBilovus20年

(Route <dynamic> route)=> route.isFirst)最初のルートまで削除したい場合。
HussnainHaidar20年

7

namedRoutesを使用している場合は、次の方法でこれを行うことができます。

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

ここで、「/ login」は、ルートスタックにプッシュするルートです。

ご了承ください :

このステートメントは、スタック内のすべてのルートを削除し、プッシュされたルートをルートにします。


4

SchedularBindingInstanceを使用したソリューションについて誰も言及しなかった理由はわかりませんが、パーティーに少し遅れましたが、これが最初にここで回答された正しい方法だと思います

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

上記のコードは、「/ login」へのすべてのルートとナビゲーションを削除します。これにより、コールバックをスケジュールして、新しいルートに移動する前にすべてのフレームがレンダリングされるようになります。


2

これは私のために働いています。実際、私はブロックで作業していましが、私の問題はログイン画面のブロックでした。ログアウト後に更新されませんでした。以前のモデルデータを保持していました。でも、間違ったエントリを入力しましたホーム画面に行きました。

ステップ1:

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

どこ、 UIData.initialRoute = "/" or "/login"

ステップ2:

画面の更新に取り組んでいます。あなたがブロックで働いているなら、それは非常に役に立ちます。

runApp(MyApp());

どこ、 MyApp() is the root class.

ルートクラス(つまりMyApp)コード

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

私がこれを正しくやっているかどうかわからない

しかし、これはルートウィジェットまでポップする私のユースケースに適しています

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.