flutter-web - Mencegah initialRoute memulai saat aplikasi diluncurkan dengan rute berbeda melalui bilah alamat browser?

Aug 21 2020

Baru di Flutter.

Saya membuat aplikasi yang memiliki layar splash yang awalnya muncul saat pengguna membuka aplikasi. Setelah 3 detik, aplikasi akan menampilkan login atau layar dasbor, tergantung pada status otentikasi.

Ini kode saya.

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

Saya telah men-debug aplikasi dengan server web. Saat aplikasi diluncurkan dengan url localhost: 8000 /, semuanya tampak baik-baik saja. Namun, jika aplikasi dimulai dengan url localhost: 8000 / notes, splash screen, menurut saya, masih dimulai. Yang terjadi adalah aplikasi akan menampilkan layar catatan, kemudian setelah 3 detik, aplikasi akan membuka layar catatan lain.

Ada ide?

Jawaban

6 Spatz Aug 24 2020 at 21:21

Karena render pertama selalu dimulai pada root '/', sebaiknya gunakan jalur Anda sendiri untuk layar splash, seperti

initialRoute: '/splash'.

Untuk menyembunyikan jalan ini di address bar, ganti rute peta dengan rute Generator:

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

Lihat karena logika utamanya adalah kita tidak dapat menunggu dalam status init sehingga halaman akan dibangun terlepas dari logika apa pun yang Anda berikan. Saya punya solusi untuk ini, mungkin ada beberapa kemajuan atau solusi bagus lainnya juga, jadi inilah yang akan saya gunakan.

Saya akan menggunakan konsep pembangun masa depan. Yang akan dilakukannya adalah menunggu server saya dan kemudian membangun seluruh aplikasi.

Jadi prosesnya

  1. Dalam penggunaan main.dart Anda

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

Sekarang MyApp Stateless Widget yang akan membantu kami memilih jalur kami

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

Pertama-tama, flutter-web seperti Aplikasi Halaman Tunggal lainnya mendukung perutean berbasis hash. Alhasil jika ingin mengakses

localhost: 8000 / catatan

Anda harus mengaksesnya sebagai

localhost: 8000 / # / catatan

Cara yang lebih bersih untuk menangani status autentikasi

Panggil fungsi getAuthState sebelum runApp () untuk memastikan bahwa status autentikasi disetel sebelum aplikasi diinisialisasi. Dan berikan authState ke widget SplashScreen sebagai parameter.

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

Dan jika Anda ingin cara yang lebih bersih untuk menangani status autentikasi, Anda harus menggunakan solusi manajemen status seperti Provider.