flutter-web - Mencegah initialRoute memulai saat aplikasi diluncurkan dengan rute berbeda melalui bilah alamat browser?
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
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',
);
}
}
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
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,
);
}
}
}
},
);
}
}
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.