flutter-web - 当应用程序通过浏览器的地址栏以不同的路由启动时,避免 initialRoute 启动?
Posted
技术标签:
【中文标题】flutter-web - 当应用程序通过浏览器的地址栏以不同的路由启动时,避免 initialRoute 启动?【英文标题】:flutter-web - Avoid initialRoute from initiating when the app launched with a different route via the browser's address bar? 【发布时间】:2020-12-09 23:12:35 【问题描述】: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 秒后,应用程序将打开另一个笔记屏幕。
有什么想法吗?
【问题讨论】:
你找到解决办法了吗? 如果您没有使用 Navigator 2.0,那么接受的答案应该可以解决上述问题。 【参考方案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
Now 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,
);
,
);
【讨论】:
【参考方案2】:因为第一次渲染总是从根“/”开始,所以最好使用自己的初始屏幕路径,例如
initialRoute: '/splash'
.
要在地址栏中隐藏此路径,请将 routes 地图替换为路由生成器:
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',
);
【讨论】:
但是对于我的网站website.com/
,它将返回null,我将始终不得不使用website.com/splash
?【参考方案3】:
首先,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 这样的状态管理解决方案。
【讨论】:
手机版和网页版都可以用吗? 是的,它适用于移动设备和网络。虽然对于 web,如果您想要更好的路由解决方案,您可以查看 Navigator 2.0以上是关于flutter-web - 当应用程序通过浏览器的地址栏以不同的路由启动时,避免 initialRoute 启动?的主要内容,如果未能解决你的问题,请参考以下文章
flutter-web:通过 Location 插件获取 web 上的位置
如何在小部件的容器内显示 pdf [flutter-web]
如何防止platformViewRegistry出错[flutter-web]
flutter-web: build_runner getter 'typeArguments' 没有为类 'Annotation' 错误定义