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(),
  },
);

splash_screen.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...
}

웹 서버로 앱을 디버깅하고 있습니다. url localhost : 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(),
    },
  ));
}

splash_screen.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(),
      ),
    );
  }
}

인증 상태를보다 깔끔하게 처리하려면 Provider와 같은 상태 관리 솔루션을 사용해야합니다.