釋出時間:2021年4月29日 - 5分鐘閱讀
照片:Max Avans on Pexels
如果你是直接來到這個頁面,請確保你在開始這個頁面之前,先瀏覽一下《走向Flutter Web Part:1》。
現在你可能想知道?為什麼我們需要再次處理路由?
試著在網路上重新整理專案中的任何一個螢幕,你會發現整個專案重新構建,你的應用程式從第一個螢幕開始,或者你也可能觀察到一個紅色的螢幕,就像我在aqi_monitor專案中重新整理LocationScreen時那樣。
讓我們分析一下為什麼會發生這種情況?
在引擎蓋下發生的事情是,資料只持續到我們重新整理Flutter專案的時候。所有那些我們通過建構函式傳遞給特定螢幕的值都變成了空值,因為沒有以前的上下文。類似的問題開始出現在狀態管理包中,比如provider,因為我們的Provider物件被返回到他們的基本狀態。
如果你使用Navigator 1.0設定了路由,你應該遷移到支援網路的Navigator 2.0,或者使用像Fluro這樣的包。
Fluro如何解決這個問題?
Fluro提供了一些開箱即用的功能,這些功能是。
- 查詢引數的解析
- 每個螢幕的功能處理程式
- 在手機和網頁上的工作完全相同
- 很容易根據平臺型別在螢幕之間新增過渡。
我們可以按照以下步驟在我們的專案中設定Fluro:----。
1. 在pubspec.yaml檔案中新增fluro的依賴項
dependencies:
fluro: 2.0.3
複製程式碼
新增依賴後,執行flutter pub get
2. 在lib/routes/內建立FluroRoutes類,作為fluro_routes.dart
/// setting up singleton class for FluroRoutes
class FluroRoutes with FluroRouteHandlers {
/// initializing FluroRoutes
static final FluroRoutes fluroRoutesInstance = FluroRoutes._();
factory FluroRoutes() {
return fluroRoutesInstance;
}
FluroRoutes._();
void routes(FluroRouter fluroRouter) {
TransitionType transitionType;
/// setting transition on web
if (kIsWeb) {
transitionType = TransitionType.fadeIn;
}
/// setting transition on android
else if (Platform.isAndroid) {
transitionType = TransitionType.material;
}
/// setting transition on iOS
else {
transitionType = TransitionType.cupertino;
}
/// linking handlers and routes of screen
fluroRouter.define(
MyHomePage.routeName,
handler: homeScreenHandler,
transitionType: transitionType,
);
fluroRouter.define(
LocationScreen.routeName,
handler: locationScreenHandler,
transitionType: transitionType,
);
}
}
複製程式碼
在這裡,我們為FluroRoutes建立了一個單例類,我們宣告瞭一個過渡型別,它將取決於作業系統,並宣告瞭專案的所有螢幕路由,並與它們的具體處理程式相聯絡。
3. 在lib/routes/內建立FluroRouteHandlers作為fluro_route_handlers.dart
mixin FluroRouteHandlers {
/// Handler for MyHomePage
var homeScreenHandler = Handler(
handlerFunc: (
BuildContext context,
Map<String, List<String>> parameters,
) {
return MyHomePage();
},
);
/// Handler for LocationScreen
var locationScreenHandler = Handler(
handlerFunc: (
BuildContext context,
Map<String, List<String>> parameters,
) {
return LocationScreen();
},
);
}
複製程式碼
在這裡,處理程式的作用是提供所需的引數(我們將在這篇文章的後面看到)並啟動螢幕。
4. 在main.dart中設定FluroRoutes
在MaterialApp中設定你的FluroRoutes。
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final FluroRouter fluroRouter = FluroRouter();
@override
void initState() {
super.initState();
/// setting up FluroRoutes with fluroRouter
FluroRoutes().routes(fluroRouter);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "AQI Monitor",
home: MyHomePage(title: 'AQI Monitor'),
/// pass you initial screen's route in initialRoute
initialRoute: MyHomePage.routeName,
/// use fluro's generator
onGenerateRoute: fluroRouter.generator,
onUnknownRoute: (unknownRoutes) {
return MaterialPageRoute(
builder: (context) => MyHomePage(),
);
},
);
}
}
複製程式碼
在網路上,由於我們可以通過改變URL進入另一個螢幕,而這將把你帶到一個不存在於你的專案中的未知螢幕,所以我們可以重定向到專案中的一個初始螢幕(如閃屏、主螢幕),或者像這樣在你的專案中製作一個自定義的404螢幕,我們可以在onUnknownRoute中利用它。
5. 更新導航過程
現在我們已經正確地設定了Fluro,我們現在將更新每個螢幕的導航過程。
i) 使用Navigator進行簡單的導航。
Navigator.pushNamed(context, LocationScreen.routeName)。
Navigator.pushNamed(context, LocationScreen.routeName);
複製程式碼
不要使用MaterialPageRoute在螢幕間導航,只使用Navigator。
ii) 使用QueryParams來傳送資料
像這樣修改你的模型和引數。
class CityModel {
String city;
CityModel({
this.city,
});
CityModel.fromJson(Map<String, dynamic> json) {
city = json['city'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['city'] = city;
return data;
}
String toQueryParam() {
return Uri(queryParameters: toJson()).query;
}
CityModel.fromQueryParam(Map<String, dynamic> jsonMap) {
city = jsonMap['city']?.first;
}
}
複製程式碼
toQueryParam是我們上面的輔助函式,它將我們模型的JSON轉換為查詢格式。
fromQueryParam是另一個輔助函式,將我們的查詢引數轉換回模型。
現在用"?"(強制)符號連線螢幕路線名稱和查詢引數。
Navigator.pushNamed(
context,
LocationScreen.routeName + '?${cityModel.toQueryParam()}',
);
複製程式碼
在最後一步,我們現在將通過使用我們的輔助函式來修改我們的處理程式。我們在Navigator中傳遞的查詢引數,我們將在處理程式中使用fromQueryParam幫助函式將它們轉換為我們的模型,並在我們的螢幕中傳遞該模型或其值。
var locationScreenHandler = Handler(
handlerFunc: (
BuildContext context,
Map<String, dynamic> parameters,
) {
CityModel cityModel;
if (parameters != null && parameters.isNotEmpty) {
cityModel = CityModel.fromQueryParam(parameters);
}
return LocationScreen(
city: cityModel != null ? cityModel.city : null,
);
},
);
複製程式碼
現在,在網路上執行你的專案,也嘗試用與之前相同的方式重新整理螢幕。
你會觀察到,我們的螢幕在重新整理後仍然在同一個螢幕事件上,而且之前出現的紅屏也應該消失了,因為查詢引數仍然在URL中,Fluro通過處理程式將這些查詢引數傳遞給我們的螢幕,這個設定在Android和iOS上也都能順利執行。
所以這就是設定這個新的整個路由機制的好處。?
重要提示:請確保在處理程式中處理所有的引數和模型,我們從一個螢幕傳送到另一個螢幕,你只需要將它們轉換為查詢引數,在導航時與路由一起新增,然後從查詢引數解碼回到模型中。
在下一篇文章中,我們將討論如何通過保持相同的程式碼庫使UI在網路和移動端上都能響應。
如果你覺得這篇文章有用,請點選拍手圖示?並與你的朋友分享,因為這將激勵我寫更多的文章。
如有任何關於Flutter的疑問,請隨時在社交媒體平臺上與我聯絡。
通過www.DeepL.com/Translator(免費版)翻譯