翁子欣 吳明暉



摘? 要: Flutter是Google開發的一種高性能的跨平臺移動UI框架,是一套聚焦于原生體驗的分層架構。文章介紹了Flutter的框架特性和實現原理,描述了基于Flutter的圖片風格轉換App的設計過程,對App的 UI設計、不同狀態類型的關鍵Widget設計等關鍵開發步驟進行了詳細說明。開發實踐表明,基于Flutter框架進行App開發能夠在不降低用戶體驗的基礎上提高開發效率。
關鍵詞: Flutter; UI框架; Widget; 圖片風格轉換; 移動應用
中圖分類號:TP399? ? ? ? ? 文獻標識碼:A? ? 文章編號:1006-8228(2020)02-67-04
Design and implementation of image style transfer App based on Flutter
Weng Zixin, Wu Minghui
(School of Computer and Computing Science, Zhejiang University City College, Hangzhou, Zhejiang 310015, China)
Abstract: Flutter is a high performance cross platform mobile UI framework developed by Google, which is a layered architecture focusing on the original experience. This paper introduces the main framework features and implementation principles of Flutter, describes the design process of the image style transfer App based on Flutter, and describes the key development steps such as the UI design of the App and the design of key Widgets with different state types in detail. The development practice shows that the application development based on the Flutter framework can improve the development efficiency without reducing the user experience.
Key words: Flutter; UI framework; Widget; image style transfer; mobile App
0 概述
當前主流的移動應用操作系統包括Android和iOS。其中,AndroidApp的主流開發平臺為Android Studio和Eclipse,主要開發語言是Java。iOSApp則利用MacOS端的XCode進行開發,開發語言為Object-C或Swift。若要開發一款適用于這兩大系統的App,開發者需要掌握兩套不同的技術。這會大大增加研發成本和維護成本。因此,利用跨平臺框架來開發移動應用的意義十分重大[1]。
Flutter是Google在2018年2月27日世界移動大會上發布的一個跨平臺開發框架。它支持在Android和iOS上快速構建高質量的原生用戶界面,支持以毫秒級的熱重載更新應用頁面,聚焦于原生體驗的分層架構,允許用戶完全自定義設計。兼具眾多優點,Flutter這一新興的跨平臺開發框架迅速進入開發者的視野,受到業界的熱烈關注[2]。
Flutter的特別之處在于,它既不使用WebView也不使用系統原生控件,而是選擇高性能的渲染引擎來畫控件。此外,Flutter只有C/C++代碼編寫的單一層,開發者能更容易控制系統,更方便地讀取或者修改系統的組件、手勢、動畫框架和控件等等[3]。
Flutter頁面中所有的元素均為Widget。Flutter使用自己高性能引擎Skia來繪制Widget。這樣不僅可以保證在Android和iOS上UI的一致性,還可以避免對原生控件依賴而帶來的限制及高昂的維護成本。Skia是Google的一個2D圖形處理函數庫,包含字型、坐標轉換以及點陣圖,有高效能且簡潔的表現,并且提供了非常友好的API[4]。
Flutter 采用 Dart編程語言來編譯。Dart語言用預編譯的方式編譯多個平臺的原生代碼。這使得Flutter能直接與平臺通信而不需要執行上下文切換的JavaScript橋接器。Dart語言適合Flutter框架的主要原因在于它支持Flutter的兩個關鍵特性:在開發階段采用JIT模式,改動無需編譯,極大的節省了開發時間;在發布時可以通過AOT生成高效的ARM代碼以保證應用性能。并且Dart在連續分配多個對象的時候,所需消耗的資源非常少。Dart虛擬機可以快速分配內存給短期生存的對象,使很復雜的UI能在60ms內完成一幀的渲染,從而保證了平滑的展示UI滑動及動畫等效果。
1 Flutter框架特性
1.1 Widget
Flutter頁面中所有元素都是Widget。Flutter的Widget是對頁面UI的一種描述,類似于Web中的HTML。應用程序、頁面、布局、視圖、事件、通知、甚至是具體的文本樣式都統一化為Widget可以讓Flutter的代碼更加統一。Flutter在構建UI過程中形成了一個類似于iOS視圖樹的Widget樹,如圖1所示。Flutter的控件通常由許多小型、單用途的控件組成而不是擴展現有的控件類。小控件結合起來產生強大的效果。類的層次結構是扁平的,使可能的組合數量最大化。
視圖在運行時可能變化,因此Flutter引入了State來管理視圖狀態。在修改完數據后,需要主動調用setState()來觸發視圖狀態的更新。根據狀態是否可變,Widget又被分為StatefulWidget和StatelessWidget,兩者都繼承自Widget。其中StatelessWidget是指無可變狀態的Widget,這類Widget的狀態只由創建Widget時傳入的參數決定,一旦創建,其在頁面上展示的效果就不再改變。而StatefulWidget存在可變狀態。當通過setState()改變狀態時,Flutter就會重新渲染該Widget。
1.2 布局
主要使用了Row、Column、Container、Expanded、Stack等。Row、Column提供了水平、垂直方向的布局,Stack提供了堆疊方式的布局,各種容器有不同的特性,可根據實際頁面需求選擇搭配不同的布局。
1.3 插件
Flutter有很多功能強大的插件[5],比如:狀態管理插件、推送、QQ、事件總線Event Bus、Toast提示、圖片選擇器、圖片加載等。在基于Flutter的圖片風格轉換App的設計與實現中運用到了狀態管理插件、QQ、圖片選擇器、圖片加載器、圖片緩存等。
2 基于Flutter的UI構建
UI構造過程經歷了從Widget樹轉換成Element樹再到最終渲染的RenderObject樹。如圖2所示。
其中,Widget樹主要存放渲染內容、視圖布局信息;Element存放上下文,通過Element遍歷視圖樹,Element同時持有Widget和RenderObject;Element是對應Widget在渲染樹的實例化節點。同一個Widget可以對應渲染樹中的多個Element,類似于一個視圖模板;RenderObject根據Widget的布局屬性進行layout,paint Widget傳人的內容。另外,在視圖描述Widget和真實渲染的RenderObject的中間設計的Element層對某一時刻的事件做了匯總和比對,只對真正需要修改的部分同步到真實渲染的RenderObject樹上面,提高了渲染效率。
3 圖像風格轉換App設計
這款App的主要功能是將用戶選擇的圖片按照指定風格轉換并展示。用戶可以將轉換好的圖片保存至本地相冊或分享至QQ。App的UI界面設計如圖3。
用戶首先從本地相冊或者使用相機拍攝獲取需要轉換風格的圖片。用戶選定圖片后的界面如圖3(a)。點擊不同風格對應窗口中的轉換按鈕,等待數秒后即得到對應風格的目標圖片,效果如圖3(b)所示。用戶可以向上滑動界面觸發分享功能,將轉換好的圖片分享給QQ好友,如圖3(c),也可以下滑界面觸發保存功能,將轉換好的圖片保存至本地相冊,效果如圖3(d)。
根據需要實現的功能,該App的主要組件為:圖片選擇器、圖片翻頁器、圖片風格轉換器、相機按鈕、相冊按鈕以及風格轉換按鈕。
圖片選擇器用于管理圖片選擇,將圖片從相機/相冊中導入后轉換成MemoryImage類型的圖片保存在內存中,如圖4所示。在導入圖片的過程中,可以適當壓縮圖片大小以減少內存的占用,并且根據圖片的EXIF信息把圖片旋轉到正常的角度,計算圖片的主要色調,用以確定圖片邊框顏色和按鈕控件的顏色等。圖片翻頁器用于管理各個風格的圖片。圖片風格轉換器是狀態可變的Widget,用于管理圖片轉換的狀態。其通過圖片的轉換階段來確定Widget的渲染外觀并確定是否要顯示轉換按鈕以及調用網絡請求。
4 重要Widget的實現
Widget的主要任務是實現build函數,定義Widget中其他較低層次的控件,build函數依次構建這些控件即實例化一個或者多個Element對象。通過Element對象實現UI渲染樹,直到底層渲染對象。
Flutter可以在Windows、Linux、Mac上開發,開發工具可以使用VS Code、Android Studio、IDEA等,本次開發使用Android Studio,主要因為Android Studio提供的Flutter Inspector工具可以實時審查元素,解決界面的顯示適配問題。下面舉例介紹幾個典型的狀態可變的Widget與狀態不可變的Widget的實現:
4.1 圖片選擇器(Stateful)
圖片選擇器的構造函數:
@override
Widget build(BuildContext context){
print(lastColor);
returnFutureBuilder(
future: MyTools.loadImage(_imgPath),
builder:(BuildContextcontext, AsyncSnapshot
Widget ret;
if(snapshot.hasError){
ret = Text(snapshot.error.toString());
}else{
MyImageData data = snapshot.data;
Switch(snapshot.connectionState){
CaseConnectionState.done:
lastMainColor = data.color.color;
lastTextColor = data.color.color;
lastColor = data.color;
ret=MyPageController(data,styleNames,styleJson);
ret = Text(“loading”);
}
}
return new Container(
color: lastMainColor,
child: addButtons(ret,lastColor),
); // Container
},
); //FutureBuilder
}
上述構造函數用于圖片選擇。當導入不同圖片時,該Widget需要被刷新,因此該Widget是有狀態變化的組件,需要繼承自Statefulwidget類。因為加載和計算圖片的屬性比較耗時,所以使用FutureBuilder對象來觀察這個耗時操作并根據該操作的不同階段來返回不同的Widget樹。當setState()被調用時,build方法都會重新執行以改變該Widget的狀態。
4.2 圖片風格轉換器(Stateful)
首先用Stack控件構造圖片和圖片的高斯模糊化的邊框,然后根據該控件的狀態決定是否需要加上轉換按鈕。最外層的手勢監控控件(GestureDetector)用于監視用戶的手勢,當用戶上下滑動界面時,要讓控件產生上下位移的效果。上移觸發分享的功能,下移觸發保存的功能。在手勢監控控件(GestureDetector)中編寫對應用戶下拉手勢的動畫效果:用AnimationController和Tween線性的觸發重繪函數(setState()),使得控件對應用戶下拉手勢,并且在松手之后會有回彈效果。同時,還可以調用onVerticalDragEnd事件。在用戶完成下拉操作時添加額外動畫。
4.3 圖片翻頁器(Stateless)
使用系統的PageController控件構造一個可以左右翻頁用于展示多種轉換效果的控件。該控件通過傳入itemBuilder參數告訴控件如何渲染每頁的內容。頭部的Text說明風格的種類,中間的圖片風格轉換器控件用于展示圖片。效果如圖5所示。
5 結束語
Flutter基于Skia引擎使用Dart語言搭建了一套全新的UI框架,底層調用OpenGL繪制,在Native和Flutter Engine上實現了UI的隔離。開發者在寫UI代碼時就不用再關心平臺實現,從而實現了跨平臺。此外,Flutter可以通過平臺通道與原生進行靈活通信,渲染效率非常高,其release版的流暢度堪比原生。在排版、圖標、滾動、點擊等方面,Flutter能夠實現零差異。Flutter作為一個高效開發與高性能并存的UI框架,大大提高了移動應用的開發效率。隨著Google與開源社區的不斷支持,將會有更多的開發者感受到利用Flutter框架進行開發帶來的高效體驗。相信Flutter在跨平臺移動應用開發中將成為一種新趨勢,受到業界更加熱烈的關注。
參考文獻(References):
[1] 金誠.移動應用跨平臺開發框架的比較分析[J].民營科技, 2018.10:150-152
[2] 彭娟. 跨平臺移動應用開發技術研究[J].科學咨詢(科技·管理),2017.27:59.
[3] 周勇,程子清.Flutter的原理深度剖析[J].電腦編程技巧與維護,2018.11:19-21
[4] 杜文. Flutter實戰[EB/OL].https://book.flutterchina.club/,2019-4-26.
[5] KeMao,MarkHarman,YueJia. Robotic Testing of Mobile Apps for Truly Black-Box Automation[J].IEEE Software,2017.34(2):11-16