flutter-web-アプリがブラウザーのアドレスバーを介して別のルートで起動したときに、initialRouteが開始されないようにしますか?

Aug 21 2020

Flutterは初めてです。

ユーザーがアプリを開いたときに最初に表示されるスプラッシュ画面を備えたアプリを作成しています。3秒後、アプリは認証状態に応じてログイン画面またはダッシュボード画面を表示します。

これが私のコードです。

main.dart

void main() { 
  runApp(myApp);
}

MaterialApp myApp = MaterialApp(
  initialRoute: "/",
  routes: {
    "/": (context) => SplashScreen(),
    "/signin": (context) => SignInScreen(),
    "/notes": (context) => NotesScreen(),
  },
);

スプラッシュスクリーン.dart

class SplashScreen extends StatefulWidget {
  @override
  _SplashScreenState createState() => _SplashScreenState();
}

class _SplashScreenState extends State<SplashScreen> {
  @override
  void initState() {
    super.initState();
    _goToNextScreen();
  }

  void _goToNextScreen() {
    Future.delayed(
      Duration(seconds:3),
      () async {
        AuthState authState = await Auth.getAuthState();
        String route = authState == AuthState.SIGNED_IN ? "/notes" : "/signin";
        Navigator.pushReplacementNamed(context, route);
      }
    );
  } 

  // build() override goes here...
}

私はウェブサーバーでアプリをデバッグしてきました。アプリがURLlocalhost:8000 /で起動すると、すべてが正常に見えます。ただし、アプリがURL localhost:8000 / notesで起動した場合、スプラッシュ画面はまだ開始されていると思います。アプリはメモ画面を表示し、3秒後に別のメモ画面を開きます。

何か案は?

回答

6 Spatz Aug 24 2020 at 21:21

最初のレンダリングは常にルート '/'で開始されるため、スプラッシュ画面には次のような独自のパスを使用することをお勧めします。

initialRoute: '/splash'

アドレスバーでこのパスを非表示にするには、ルートマップをルートジェネレータに置き換えます。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      onGenerateRoute: (RouteSettings settings) {

        // print current route for clarity.
        print('>>> ${settings.name} <<<');

        switch (settings.name) {
          case '/splash':
            return MaterialPageRoute(
              builder: (context) => SplashScreen(),
              // settings omitted to hide route name
            );
          case '/signin':
            return MaterialPageRoute(
              builder: (context) => SignInScreen(),
              settings: settings,
            );
          case '/notes':
            return MaterialPageRoute(
              builder: (context) => NotesScreen(),
              settings: settings,
            );
          case '/':
            // don't generate route on start-up
            return null;
          default:
            return MaterialPageRoute(
              builder: (context) => FallbackScreen(),
            );
        }
      },
      initialRoute: '/splash',
    );
  }
}


2 KrishBhanushali Aug 20 2020 at 22:58

メインロジックはinit状態で待つことができないため、提供するロジックに関係なくページが構築されることを確認してください。私はこれに対する解決策を持っています、いくつかの進歩または他の良い解決策もあるかもしれません、それでこれは私が使うものです。

私は将来のビルダーの概念を使用します。サーバーを待ってからアプリ全体をビルドします。

つまり、プロセスは

  1. main.dartでの使用

     Future<void> main() async {
       try {
         WidgetsFlutterBinding.ensureInitialized();
    
     //await for my server code and according to the variable I get I will take action
     //I would have a global parameter lets say int InternetOff
         await checkServer();
         runApp(MyApp());
       } catch (error) {
         print(error);
         print('Locator setup has failed');
     //I can handle the error here
       }
     }
    

パスの選択に役立つMyAppステートレスウィジェット

class MyApp extends Stateless Widget{
Widget build(BuildContext context) {
//Using this FutureBuilder 
    return FutureBuilder<String>(
      builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
        // AsyncSnapshot<Your object type>

// Now if InternetOff is equal to one I would make it go to home 
if(InternetOff==1) return MaterialApp(
              theme: ThemeData.light(),
              home: CheckInternet(),
              debugShowCheckedModeBanner: false,
            );
//else go to Home similarly with these if and else you can add more conditions
else {
             
              return MaterialApp(
                theme: ThemeData.dark(),
                home: UserHome(),
                debugShowCheckedModeBanner: false,
              );
            }
          }
        }
      },
    );
  }
}
tanweeranwar Aug 25 2020 at 17:09

まず第一に、他のシングルページアプリケーションと同様にflutter-webはハッシュベースのルーティングをサポートしています。その結果、アクセスしたい場合

localhost:8000 / notes

あなたはそれにアクセスする必要があります

localhost:8000 /#/ notes

認証状態を処理するためのよりクリーンな方法

runApp()の前にgetAuthState関数を呼び出して、アプリが初期化される前に認証状態が設定されていることを確認します。そして、authStateをパラメーターとしてSplashScreenウィジェットに渡します。

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  AuthState authState = await Auth.getAuthState();
  runApp(MaterialApp myApp = MaterialApp(
    initialRoute: "/",
    routes: {
      "/": (context) => SplashScreen(authState: authState),
      "/signin": (context) => SignInScreen(),
      "/notes": (context) => NotesScreen(),
    },
  ));
}

スプラッシュスクリーン.dart

class SplashScreen extends StatefulWidget {
  final AuthState authState;
  SplashScreen({Key key, this.authState}) : super(key: key);
  @override
  _SplashScreenState createState() => _SplashScreenState();
}

class _SplashScreenState extends State<SplashScreen> {
  @override
  void initState() {
    super.initState();
    _goToNextScreen();
  }

  void _goToNextScreen() {
    Future.delayed(
      Duration(seconds:3),
      () async {
        String route = widget.authState == AuthState.SIGNED_IN ? "/notes" : "/signin";
        Navigator.pushReplacementNamed(context, route);
      }
    );
  } 

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: CircularProgressIndicator(),
      ),
    );
  }
}

また、認証状態をよりクリーンに処理する方法が必要な場合は、プロバイダーなどの状態管理ソリューションを使用する必要があります。