Flutter Dynamic Widget - Build your widget on the fly

本人在某電商公司搬磚,一般來說電商APP的首頁都需要非常動(dòng)態(tài)靈活的展現(xiàn)方式,例如:某天產(chǎn)品突發(fā)奇想為后天的xx大促活動(dòng)設(shè)計(jì)了一個(gè)酷炫的UI展現(xiàn)方式,跟技術(shù)說如果按照我的這種展示交互來做的話,這個(gè)轉(zhuǎn)化率肯定能提升100%。問我們什么時(shí)候能搞定,我們一評(píng)估發(fā)現(xiàn)這個(gè)需要發(fā)版才能搞定。后天的xx大促肯定是來不及了。產(chǎn)品會(huì)覺得我們技術(shù)太差,我們也在產(chǎn)品面前抬不起頭。

電商app

對(duì)于這種問題,APP有React Native、Weex這種解決方案,但是我們調(diào)研RN后發(fā)現(xiàn),RN有很多問題,而且性能方面也不是太好。好像現(xiàn)在越來越多的公司也已經(jīng)拋棄RN了。所以我們就決定自己定義了一套UI組件協(xié)議,在Android、iOS,JS設(shè)置小程序端分別實(shí)現(xiàn)。這種方案前期工作量確實(shí)很大,但是當(dāng)你的UI組件協(xié)議越來越豐富時(shí),帶來的好處也是極大的。APP中的很多頁面我們都能做到隨時(shí)更新。甚至是能做到隨時(shí)新增一些頁面。避免APP一旦修改都需要發(fā)版的問題。極大的提升了產(chǎn)品迭代速度。帶來極大的收益。

Flutter

其實(shí)早在17年的時(shí)候,我們就已經(jīng)有關(guān)注Flutter了,那時(shí)候還是叫Sky。我們?cè)趫F(tuán)隊(duì)內(nèi)分享后覺得還是處于非常早期的階段,后面也沒有再持續(xù)關(guān)注了,沒想到Flutter在18年12月份放出了1.0正式版。Flutter天然的跨平臺(tái),支持Android,iOS。Web和桌面也在支持的計(jì)劃中??梢哉f幾乎跨了所有的平臺(tái)。而且是基于同一份代碼,注意這里跟RN還是有區(qū)別的,RN是Learn once, write everywhere.

在學(xué)習(xí)Flutter的過程中發(fā)現(xiàn)寫Flutter的Widget跟我們公司定義的那套UI協(xié)議是非常相似的。我們定義的UI協(xié)議是基于json語法,而Flutter的Widget代碼跟json幾乎一致。


sample

這里可以把Widget的類型對(duì)應(yīng)到j(luò)son string的type屬性。其他的屬性基本保持一致,這里color的屬性在json中使用#aarrggbb就行。看到這里心中就涌現(xiàn)一個(gè)想法,如果我用Flutter來實(shí)現(xiàn)一個(gè)DynamicWidget,這個(gè)Widget可以通過json來創(chuàng)建的話,這樣我只要用Flutter實(shí)現(xiàn)一遍就能天然的跨多端。而且Flutter的Widget就是天然的UI協(xié)議呀,我只要把Flutter官方的Widget轉(zhuǎn)成json然后實(shí)現(xiàn)一遍就行了。這樣用戶只要會(huì)了解了Flutter的Widget基本上就能寫出對(duì)應(yīng)的json了。用戶不需要再理解一套特殊的UI協(xié)議。我們公司的UI協(xié)議,為了兼容Android、iOS各端走的是一套特殊的UI協(xié)議,需要使用者去學(xué)習(xí)。

Flutter Dynamic Widget

說干就干,先定義一個(gè)WidgetParser接口。

/// extends this class to make a Flutter widget parser.
abstract class WidgetParser{

  /// parse the json map into a flutter widget.
  Widget parse(Map<String, dynamic> map);

  /// check the matched widget type. for example:
  /// {"type" : "Text", "data" : "Denny"}
  /// if you want to make a flutter Text widget, you should implement this
  /// method as "Text" == widgetName, for more details, please see
  /// @TextWidgetParser
  bool forWidget(String widgetName);
}

parse方法解析json得到Flutter的Widget,forWidget方法表示這個(gè)Parser是對(duì)應(yīng)json中對(duì)應(yīng)的type屬性。我們來實(shí)現(xiàn)一個(gè)Container widget的Parser, 如下:

class ContainerWidgetParser extends WidgetParser{
  @override
  bool forWidget(String widgetName) {
    return "Container" == widgetName;
  }

  @override
  Widget parse(Map<String, dynamic> map) {
    Alignment alignment = parseAlignment(map['alignment']);
    Color color = parseHexColor(map['color']);
    BoxConstraints constraints = parseBoxConstraints(map['constraints']);
    //TODO: decoration, foregroundDecoration and transform properties to be implemented.
    EdgeInsetsGeometry margin = parseEdgeInsetsGeometry(map['margin']);
    EdgeInsetsGeometry padding = parseEdgeInsetsGeometry(map['padding']);
    Map<String, dynamic> childMap =  map['child'];
    Widget child;
    for(var parser in DynamicWidgetBuilder.parsers){
      if (parser.forWidget(childMap['type'])){
        child = parser.parse(childMap);
        break;
      }
    }
    return Container(
      alignment: alignment,
      padding: padding,
      color: color,
      margin: margin,
      width: map['width'],
      height: map['height'],
      constraints: constraints,
      child: child,
    );
  }

}

你需要做的就是解析json的各個(gè)屬性,然后最后拼裝一個(gè)Container對(duì)象。很簡(jiǎn)單把?;谝陨系南敕ǎ野褜?shí)現(xiàn)放在github上,大家可以在這里查看源碼和各個(gè)實(shí)現(xiàn)的Widget的demo。同時(shí)也發(fā)布到dart pub上了。
github:https://github.com/dengyin2000/dynamic_widget
dart pub:https://pub.dartlang.org/packages/dynamic_widget

目前只是實(shí)現(xiàn)了幾個(gè)Flutter Widget,計(jì)劃是把Flutter官方的widget都實(shí)現(xiàn)一遍。大家如果有問題的話,歡迎隨時(shí)聯(lián)系我。

demo1.gif
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 特別說明 當(dāng)前博客平臺(tái)賬號(hào)已廢棄,如果有使用細(xì)節(jié)問題請(qǐng)前往我新博客平臺(tái)進(jìn)行討論交流。 個(gè)人博客平臺(tái) HuRuWo的...
    善篤有余劫閱讀 5,087評(píng)論 0 30
  • 國(guó)慶后面兩天在家學(xué)習(xí)整理了一波flutter,基本把能擼過能看到的代碼都過了一遍,此文篇幅較長(zhǎng),建議保存(star...
    Nealyang閱讀 4,446評(píng)論 1 17
  • 目錄 一、Flutter 為何使用Dart開發(fā)語言二、Flutter的UI系統(tǒng)1.特點(diǎn)2.架構(gòu)簡(jiǎn)介2.1 Flut...
    十拿九穩(wěn)啦閱讀 3,875評(píng)論 3 28
  • 原文在此,此處只為學(xué)習(xí) Widget與ElementWidget主要接口Stateless WidgetState...
    lltree閱讀 4,617評(píng)論 0 1
  • 14/21 李雯 深圳【每日一結(jié)構(gòu)】結(jié)構(gòu)思考力21天思維改善訓(xùn)練營(yíng) 序:近期二手房買賣糾紛案件呈現(xiàn)井噴狀態(tài)。 G:...
    閃亮Living閱讀 188評(píng)論 0 0

友情鏈接更多精彩內(nèi)容