本文列舉了項目開發使用Flutter會遇到的問題,以及如何使用Flutter module在現有項目中集成Flutter,並對其原理進行了分析。java
最近在作的一個商業項目,徹底的使用Flutter編寫的,這其中的坑,只有寫過的人才能體會到。android
在論述純Flutter項目問題以前,我先表述下個人觀點(僅限於純Flutter項目,目前時間2018年6月26日,不排除Flutter的發展,讓個人觀點改觀):ios
對於使用Flutter的初衷,我相信大部分領導都是出於提升生產力。可是目前就咱們的項目來看,相同的時間,若是改用Native去寫,我以爲二者進度並無多大的差別,可能Native端反而會更快一些。目前Flutter中很是常見的一些控件功能都沒法知足,每每在輪子上須要耗費大量的時間,反而在業務層面花費的時間不多。git
適配問題:Flutter說的是跨平臺,可是沒有很完美的解決各個屏幕差別所帶來的問題。實際上仍是須要去作一些適配;程序員
性能問題:目前看這個問題特別突出,在一些性能低的Android手機上,會出現一些卡頓問題。在一些高端機型上,一些轉場動畫,效果也不是特別理想,一旦涉及到一些複雜的頁面,切換頁面就會出現很明顯的卡頓問題;github
硬件相關問題:這個也是Flutter須要急需解決的問題,第三方硬件相關插件質量良莠不齊,官方插件質量也堪憂。例如官方的camera插件,各類crash問題。web
生命週期問題:插件層對生命週期的監控,是App級別的,沒法針對某一個頁面。Flutter中控件也沒有很明確的生命週期這一律念,就是兩三種狀態的切換,沒有像React中的生命週期,更不用說像Native中的那樣。性能優化
上面這些問題是在項目中實際遇到的,固然一些問題經過變換實現手段能夠規避,一些輪子本身花些時間造。一個新技術的初期,尤爲是這種跨平臺技術,選擇all in的,仍是須要再三考量。app
前面說的一些問題,並非說Flutter很是差勁。若是說生態很是成熟的Flutter,我會很是願意去使用,這項技術目前看確實挺有吸引力的。拋開寫着寫着就感受本身像個web開發以外,其實寫起來並無太多的負擔。異步
移動端技術如今已是處在一個很是成熟平穩的時期,因此跨平臺技術纔會如此的迫切,單純的去召集兩個team開發兩個端,這種成本在目前來看確實比較高,尤爲是一些日活較低的產品。
前段時間,炒得沸沸揚揚的Airbnb拋棄RN的新聞,讓你們對RN以及跨平臺技術產生了一些不肯定。跨平臺技術歷來都是公司層面的需求,並非程序員我的的需求。何況,任何技術都不能忽略平臺背後的商業推進,我不是一個跨平臺技術的追求者,我我的也一直以爲跨平臺是個僞命題。
追求純粹的跨平臺,無疑是條死路,平臺差別中追求共通點,這纔是大出路。我想這也是爲何Flutter要去實現,在現有項目中集成Flutter的緣由吧。
官方一直在努力讓Flutter更好的接入現有的移動端(iOS/Android)項目中,這個目的不言而喻。若是這個弄很差,確定不會有太多商業項目願意去使用Flutter,就像RN同樣。
Android端方案目前稍微算是穩定一些,可是性能效率方面仍是堪憂。所以本文主要偏重於介紹Android端目前來講算是相對穩定的一種方案,也就是採用Flutter module模板的方式。
咱們默認安裝的Flutter版本是beta版本,目前(2018年6月29日)版本尚未支持在現有項目中集成Flutter module的模板功能。
flutter channel
通常的用戶能夠看到輸出以下信息:
Flutter channels: * beta dev master
所以,咱們切換到master分支。
flutter channel master
而後運行更新命令
flutter upgrade
這個功能是在2018年6月22日發佈在master分支的,目前也只是早期的preview版本。咱們在一個Android項目目錄同級目錄下建立模板工程。
flutter create -t module flutter_module
建立的項目目錄下面有兩個隱藏文件夾,分別是.android和.ios。其中.android中包含後續咱們須要使用的一些代碼,例如封裝好的Flutter以及FlutterFragment的Java代碼。
修改Android項目根目錄的settings.gradle,將Flutter module做爲一個子工程添加到項目中
include ':app' // assumed existing content setBinding(new Binding([gradle: this])) // new evaluate(new File( // new settingsDir.parentFile, // new 'flutter_module/.android/include_flutter.groovy' // new )) // new
Sync一下,能夠發現添加了兩個module到項目中了。其中一個是flutter的module,其中包含了一些簡單的封裝,供Java代碼調用。另外一個是package_info的module,是一個Flutter插件,其代碼很是簡單,就是獲取app名稱、包名、版本等信息。
在app的build.gradle中添加依賴
dependencies { implementation project(':flutter')
Sync一下,不出意外的話,應該不會有什麼錯誤,到此,這個Flutter module就被添加到了Android項目中了。
使用Flutter module中的Java API,添加一個Flutter view到頁面上。
val flutterView = Flutter.createView( this@MainActivity, lifecycle, "route1" ) val layout = FrameLayout.LayoutParams(600, 800) layout.leftMargin = 100 layout.topMargin = 200 addContentView(flutterView, layout)
上面代碼是添加到一個文本的點擊事件中的,其中FlutterView能夠看做是Flutter代碼展現的容器。展現的寬600高800的部分,其實是Flutter的代碼生成的。其中的route1則是寫在Flutter中的,生成了一個綠色背景的Container。代碼以下
case 'route1': return Container( child: Center(child: Text('Route 1\n${packageInfo.appName}')), color: Colors.green, );
在真機上運行,效果挺差勁的,點擊了文本事後,會先黑一下屏,而後將這個FlutterView添加到頁面上,整個過程也很緩慢,這樣子確定是無法在項目中使用。
到此,已經完成了Android調用Flutter代碼的全過程了,咱們來梳理一下整個流程:
這個目前是在試驗階段,若是有願意嘗試的,也能夠按照官方的例子去走一遍,不過你們最好也得有心理準備,官方文檔上說會出現一系列問題,在此筆者不作進一步的嘗試了。整個過程並不複雜,也是須要切換到master分支上去進行的。若是這種方案穩定下來,確定會比上面的那種module方式更加的方便。
目前也是試驗階段,若是想要嘗試的話,也須要切換到master分支上去進行的。
FlutterView在插件層面比較常見,是Flutter層的一個Java API。實際上能夠把它看是Android端的一個View,只不過裏面包含的是Flutter的內容。例如將相機封裝成一個Flutter控件,就須要藉助FlutterView,將預覽輸出到FlutterView上。
在Native項目中集成Flutter,FlutterView也起到了很重要的做用。Flutter層內容的輸出,也都是經過FlutterView來實現的。
FlutterView繼承自SurfaceView,它像是一個大雜燴,它包含了或者監聽了儘量多的事件,例如鍵盤、物理按鍵、生命週期、廣播、Surface回調、橫豎屏切換等等。基本上把Android端一個View可能存在的一些事件或者狀態,都添加上去,讓Flutter層可以得知儘量多的狀態和回調。
FlutterView除去各類監聽事件,內部實際的工做是由FlutterNativeView去實現的。其本質也是一個插件接口,只不過是Native調用Flutter層的,它們之間經過MethodChannel進行通訊的。
經過Flutter module中的flutter模塊,咱們能夠看出其本質上仍是經過MethodChannel進行調用的。這是Flutter官方提供的一種插件能力,並非說只能單向調用,也能夠在Native端調用Flutter。
可是呢,這個調用是異步的,目前看,Native端調用Flutter層效果並非很理想。目前筆者也是在debug下進行測試的,release環境下應該會好一點吧。若是須要在Native項目中集成Flutter,則還須要進行優化,例如提早初始化等。
在Flutter module沒有被放出以前,其餘公司通常都是怎麼去實現這種混編的呢。如上面所述,我以爲都是利用了FlutterView。若是咱們不依賴Flutter module,在Native中引入Flutter庫,直接使用FlutterView進行頁面編寫,這個自己也不是什麼困難的事情。難就難在進行性能優化達到上線的條件。
MethodChannel這種Natvive與Flutter之間的通訊方式,給了這種混編的一種可能性。仍是期待Flutter官方能把這種混編模式完善起來。
最後說一句,Flutter裏面造起輪子來,簡直就是太沒人性了。
筆者建的一個Flutter學習相關的項目,Github地址,裏面包含了筆者寫的關於Flutter學習相關的一些文章,會按期更新,也會上傳一些學習demo,歡迎你們關注。