flutter-web-アプリがブラウザーのアドレスバーを介して別のルートで起動したときに、initialRouteが開始されないようにしますか?
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秒後に別のメモ画面を開きます。
何か案は?
回答
最初のレンダリングは常にルート '/'で開始されるため、スプラッシュ画面には次のような独自のパスを使用することをお勧めします。
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',
);
}
}
メインロジックはinit状態で待つことができないため、提供するロジックに関係なくページが構築されることを確認してください。私はこれに対する解決策を持っています、いくつかの進歩または他の良い解決策もあるかもしれません、それでこれは私が使うものです。
私は将来のビルダーの概念を使用します。サーバーを待ってからアプリ全体をビルドします。
つまり、プロセスは
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,
);
}
}
}
},
);
}
}
まず第一に、他のシングルページアプリケーションと同様に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(),
),
);
}
}
また、認証状態をよりクリーンに処理する方法が必要な場合は、プロバイダーなどの状態管理ソリューションを使用する必要があります。