配置routes參數(shù)
公司專(zhuān)注于為企業(yè)提供成都做網(wǎng)站、網(wǎng)站建設(shè)、微信公眾號(hào)開(kāi)發(fā)、商城網(wǎng)站建設(shè),小程序開(kāi)發(fā),軟件按需網(wǎng)站建設(shè)等一站式互聯(lián)網(wǎng)企業(yè)服務(wù)。憑借多年豐富的經(jīng)驗(yàn),我們會(huì)仔細(xì)了解各客戶(hù)的需求而做出多方面的分析、設(shè)計(jì)、整合,為客戶(hù)設(shè)計(jì)出具風(fēng)格及創(chuàng)意性的商業(yè)解決方案,成都創(chuàng)新互聯(lián)更提供一系列網(wǎng)站制作和網(wǎng)站推廣的服務(wù)。
main函數(shù):
使用
單參數(shù)
多參數(shù)
參考了: Flutter命名路由及傳參的深度實(shí)踐與解讀 ;
flutter也有自己的生命周期,不像Android中Application、Activity、Fragment生命周期分得這么明細(xì),flutter中只在StatefulWidget維護(hù)的State中維護(hù)了5個(gè)生命周期函數(shù)(可用于A(yíng)pp中的頁(yè)面跳轉(zhuǎn),相當(dāng)于A(yíng)ndroid中View的生命周期)。而Activity中的生命周期可以通過(guò)實(shí)現(xiàn)WidgetsBindingObserver 接口,在didChangeAppLifecycleState()中獲取狀態(tài)回調(diào)。
initState()--didChangeDependencies()--deactivate()--dispose() didUpdateWidge()
1.Widget A打開(kāi)Widget B: 調(diào)用 Navigator.push(B)
2.Widget B從Widget A退出: 調(diào)用Navigator.pop()
可以看出, Flutter打開(kāi)、關(guān)閉Widget時(shí)跟安卓、iOS的時(shí)序一樣, 都是先處理即將顯示的界面。
Flutter提供了WidgetsBindingObserver來(lái)監(jiān)聽(tīng)AppLifecycleState, 而AppLifecycleState有4種狀態(tài):
1、 resumed 界面可見(jiàn), 同安卓的onResume。
2、inactive界面退到后臺(tái)或彈出對(duì)話(huà)框情況下, 即失去了焦點(diǎn)但仍可以執(zhí)行drawframe回調(diào);同安卓的onPause;
3、paused應(yīng)用掛起,比如退到后臺(tái),失去了焦點(diǎn)且不會(huì)收到 drawframe 回調(diào);同安卓的onStop;
4、suspending, iOS中沒(méi)用,安卓里就是掛起,不會(huì)再執(zhí)行 drawframe 回調(diào);
5、關(guān)于drawframe回調(diào):Vsync信號(hào)到來(lái)之后,Engin會(huì)按順序回調(diào) window 的兩個(gè)回調(diào)函數(shù): onBeginFrame() 和 onDrawFrame() 。這兩個(gè)回調(diào)是 SchedulerBinding 初始化的時(shí)候設(shè)置給 window 的。對(duì)應(yīng)的是 SchedulerBinding.handleBeginFrame() 和 SchedulerBinding.handleDrawFrame() 。
應(yīng)用場(chǎng)景:
1、初次打開(kāi)widget時(shí),不執(zhí)行AppLifecycleState的回調(diào);
2、按home鍵或Power鍵, AppLifecycleState inactive----AppLifecycleState pause
3、從后臺(tái)到前臺(tái):AppLifecycleState inactive---ApplifecycleState resumed
4、back鍵退出應(yīng)用: AppLifecycleState inactive---AppLifecycleState paused
如果我們目前的項(xiàng)目是Android的,但是接下來(lái)我們希望部分頁(yè)面可以使用Flutter進(jìn)行開(kāi)發(fā),甚至我們希望在Native頁(yè)面中嵌入FlutterUI組件,那么我們?cè)撊绾螌?shí)現(xiàn)呢?
假設(shè)你現(xiàn)在A(yíng)ndroid項(xiàng)目的目錄的結(jié)構(gòu)是這樣的
這時(shí)候如果你想創(chuàng)建一個(gè)Flutter模塊,使得Android模塊和Flutter模塊之間可以進(jìn)行交互,我們可以通過(guò)Android Studio新建一個(gè)Flutter Module,具體過(guò)程是:File — New — New Module ,之后選擇Flutter Module,指定Project Location的路徑為
也就是說(shuō),最終你的項(xiàng)目結(jié)構(gòu)會(huì)是這樣的
接下來(lái)在A(yíng)ndroid Module的 build.gradle 文件中添加flutter依賴(lài)
先創(chuàng)建一個(gè)Flutter頁(yè)面
這里比較重要的是 window.defaultRouteName 這個(gè)字段,這個(gè)字段可以接收從Native傳遞過(guò)來(lái)的參數(shù) (下文我們會(huì)介紹原生傳遞參數(shù)的方法),也就是說(shuō)通過(guò)這個(gè)字段我們就可以進(jìn)行Flutter頁(yè)面的路由的分發(fā)
我們可以直接在A(yíng)ndroid的 MainActivity 中啟動(dòng)一個(gè) FlutterActivity ,這里的 initialRoute 方法中傳遞的參數(shù)就對(duì)應(yīng)Flutter層的 window.defaultRouteName
注意:需要在 AndroidManifest.xml 注冊(cè) FlutterActivity
自己創(chuàng)建一個(gè) FlutterAppActivity 繼承自 FlutterActivity
在 MainActivity 中啟動(dòng) FlutterAppActivity (另外別忘了在 AndroidManifest.xml 中注冊(cè) FlutterAppActivity )
兩種啟動(dòng)方式的區(qū)別
如果單純只是想打開(kāi)一個(gè)Flutter頁(yè)面,兩種方式實(shí)際上基本沒(méi)有太大區(qū)別,第一種方式也許還會(huì)更簡(jiǎn)單一點(diǎn)。但是,在Flutter開(kāi)發(fā)中,我們往往還需要開(kāi)發(fā)一些Native插件供Flutter調(diào)用,如果使用復(fù)寫(xiě) FlutterActivity 的方式更有利于我們?cè)?FlutterActivity 中注冊(cè)我們的Native插件,所以實(shí)際開(kāi)發(fā)中一般推薦使用第二種方式
擴(kuò)展思考
initialRoute 從名稱(chēng)上看起來(lái)是Flutter提供給我們進(jìn)行Native與Flutter交互的路由跳轉(zhuǎn)的,但是實(shí)際上他就是一個(gè)字符串,我們不僅僅可以傳遞一個(gè)路由名稱(chēng),有時(shí)候我們也可以通過(guò)這個(gè)參數(shù)傳遞一串JSON數(shù)據(jù),然后在Flutter端進(jìn)行解析,這樣我們就可以通過(guò)這個(gè)參數(shù)做更多的事情
activity_main.xml
FrameLayout 用于承載Flutter組件
MainActivity.java
使用 FragmentManager 將 FlutterFragment 添加到 FrameLayout 容器中
運(yùn)行結(jié)果
上半部分是原生的TextView,下半部分是Flutter的Text組件
本節(jié)主要介紹了Native和Flutter之間的頁(yè)面跳轉(zhuǎn),以及同一個(gè)頁(yè)面中Native與Flutter組件的組合。接下來(lái)會(huì)介紹如何編寫(xiě)Android插件與Flutter進(jìn)行數(shù)據(jù)交互
現(xiàn)象:
flutter頁(yè)面通過(guò)present跳轉(zhuǎn)原生頁(yè)面后,原生頁(yè)面上的點(diǎn)擊會(huì)首先響應(yīng)下面的flutter頁(yè)面中的內(nèi)容(比如按鈕什么的)。
這是flutter框架一直存在的一個(gè)bug。在github上有相關(guān)的issue。
原因推測(cè):
推測(cè)是flutter對(duì)控制器(或者view)加了分類(lèi),重寫(xiě)了控制器的點(diǎn)擊事件,用來(lái)計(jì)算是否在對(duì)應(yīng)的點(diǎn)擊位置有flutter響應(yīng)事件。沒(méi)有的話(huà)再扔出去點(diǎn)擊事件。
解決方案1:
在原生控制器中,加入點(diǎn)擊事件的幾個(gè)方法的空實(shí)現(xiàn),用以覆蓋flutter框架中的實(shí)現(xiàn):
-(void)touchesBegan:(NSSetUITouch * *)touches withEvent:(UIEvent *)event{
}
-(void)touchesMoved:(NSSetUITouch * *)touches withEvent:(UIEvent *)event{
}
-(void)touchesCancelled:(NSSetUITouch * *)touches withEvent:(UIEvent *)event{
}
-(void)touchesEnded:(NSSetUITouch * *)touches withEvent:(UIEvent *)event{
}
讓事件不被flutter截獲即可。
解決方案2:
直接切換window的根控制器到原生控制器即可。別忘暫時(shí)保存flutter控制器。
在返回時(shí)再切換回flutter中。
解決方案3:
在flutter跳轉(zhuǎn)到原生頁(yè)面之前,在flutter中加上一個(gè)蒙層,用來(lái)隔絕手勢(shì)往flutter下面的view傳遞。原生頁(yè)面返回flutter時(shí)再移除這個(gè)蒙層。
背景:flutter組件嵌套都很深,依次傳遞數(shù)據(jù)很麻煩,所以最好是能夠跨組件傳遞。有三張跨組件的方式:InheritedWidget、Notification、Eventbus.
是一種自上而下的傳遞數(shù)據(jù)的方式。
使用步驟:
它的數(shù)據(jù)流動(dòng)方式和InheritedWidget剛好相反,從子控件向上面?zhèn)鬟f。
具體使用
跟android 原生的eventbus原理和使用一樣。