Gbox開源:讓你用上大廠的APP動態業務容器

1 咱們要解決什麼問題?

在線上對於某些適用於要求強展現、輕交互、高可配場景,RN和WebView顯得不夠靈活,性能表現也不夠好,例如首頁feed流卡片,一級頁面的活動頁等,這些頁面的邏輯不強,也每每只是須要局部動態化。php

對於這些應用場景,美團APP團隊有本身的一套閉源的動態化容器MTFlexbox來應對,可讓佈局快速開發上線,而且不受發版限制。以前在美團實習期間有幸學習過MTFlexbox,這裏我要感謝一下美團APP終端業務研發組的同窗們,以及我本來的Leader。java

在實習結束返校以後,本身一直想作個實習總結,但又不知道以什麼爲主題比較合適。對於MTFlexbox理解得以及其適用的業務特色理解的還算深入,因此最終我選擇了嘗試本身去設計實現一個與MTFlexbox功能相似的開源框架Gbox。git

Gbox使用kotlin開發,在Apache開源協議下發布,不包含MTFlexbox的任何源代碼,也不是MTFlexbox的兼容版本,它是一個徹底基於開源軟件實現的全新開源軟件。github

Gbox從設計到技術選型再到編碼再到bug修復,足足花了我大半個月的時間,這期間本身踩了好多litho、Drawable和Canvas的坑,對於整個Android渲染架構的理解也更深入了。如今Gbox已經基本基本穩定,達到可用狀態,我將其開源在github上->Gbox(從版本號0.1.1開始,可以穩定使用)。apache

2 Gbox擁有如下特色/優點

Gbox是對業務以及性能友好的:json

  • 異步測量佈局,解放主線程
  • 消除View層級,而且直接使用Drawable進行渲染,與WebView相比有更大的性能優點
  • 異步圖片加載,使用輕量級Glide做爲圖片加載引擎,全部圖片都可以從網絡加載,而且不會觸發額外的佈局更新
  • 先後端分離,後端下發佈局+數據的json,可集成在數據接口下發,本地自主解析渲染布局
  • 單View接入,基本無入侵性,可用於替換現有的任意一個靜態展現型的View,並支持曝光埋點、點擊埋點、點擊時間處理等事件
  • 提供完整的開發工具鏈,佈局開發可實時預覽,提供佈局實時預覽APP(overview)和mock工具,可經過掃碼鏈接電腦進行實時預覽調試
  • 基於flexbox佈局模型,包含豐富的可配置樣式,例如邊框顏色,圓角,圖片,文本等
  • 強大的佈局內表達式解析功能,包括數學運算,for語句,三元表達式,簡單的java方法調用,使用表達式時需使用'${}'包圍
  • 屏幕自適應,佈局使用的單位爲是設備獨立的pt,以設備屏幕寬度爲準,1pt=(設備屏幕寬度像素值/360)像素
  • 使用kotlin編碼,代碼實現很是簡潔,很適合閱讀學習
  • 對邏輯友好,支持原生View嵌入Gbox

3 實現效果

Gbox有豐富的樣式能力,可以實現圓角、高斯模糊、漸變色、文本、網絡圖片的繪製。得益於facebook開源的litho,佈局測量的工做能夠在異步線程進行,主線程只負責繪製,大大減輕了主線程的負擔,因此滑動幀數能夠達到媲美MTFlexbox的高度。後端

同時,得益於Apache開源的el表達式類庫(使用在嵌入式tomcat上的版本),使得Gbox樣式模板xml中的全部屬性均支持表達式解析,包括但不限於函數調用、算數運算、三元表達式、java bean訪問,同時Gbox還支持相似Jsp中的for語句。tomcat

3.1 對比截圖

對比美團首頁線上方案MTFlexbox,左爲MTFlexbox(美團APP),右爲Gbox(Gbox的實時預覽APP)。 bash

3.2 佈局樣式

下面是上面右邊截圖渲染出來所須要的佈局樣式,以爲長的同窗能夠先跳過。網絡

<?xml version="1.0" encoding="utf-8"?>
<Flex background="WHITE" borderRadius="12" flexDirection="column" width="300">
    <Flex alignItems="center" marginLeft="10" marginTop="12" flexDirection="row">
        <Text textStyle="bold" textSize="16" text="碧藍航線電子科大店">
        </Text>
        <Text marginTop="2" paddingLeft="4" paddingRight="4" background="${draw:gradient(l2r,'#EE9611','#F7C709')}" borderRadius="3" marginLeft="12" text="外賣" textSize="10"/>
    </Flex>
    <Flex marginLeft="10" marginTop="5" flexDirection="row">
        <Text textColor="#E6941A" textSize="11" text="4.1分">
        </Text>
        <Text textColor="#808080" textSize="11" text=" | 月售929">
        </Text>
        <Text textColor="#808080" textSize="11" text=" | 配送¥0">
        </Text>
        <Flex flexGrow="1">
        </Flex>
        <Text textColor="#808080" marginLeft="10" marginRight="10" textSize="11" text="31分鐘送達">
        </Text>
    </Flex>
    <Flex alignItems="center" marginLeft="10" marginTop="5">
        <Text borderRadius="3" paddingLeft="4" paddingRight="4" textSize="10" background="${draw:gradient(l2r,'#F70909','#FF6600')}" textColor="WHITE" text="優惠">
        </Text>
        <Text textColor="#808080" marginLeft="5" textSize="12" text="首單減12">
        </Text>
    </Flex>
    <Flex height="100" flexGrow="1" marginBottom="10" marginLeft="7" marginRight="7" marginTop="8" flexDirection="row">
        <Flex flexDirection="column" justifyContent="center" marginLeft="3" marginRight="3" flexGrow="1">
            <Image borderRadius="4" scaleType="fitXY" flexGrow="1" url="${image2}">
            </Image>
            <Text marginTop="5" textAlign="center" textSize="11" text="拉菲">
            </Text>
        </Flex>
        <Flex flexDirection="column" justifyContent="center" marginLeft="3" marginRight="3" flexGrow="1">
            <Image borderRadius="4" scaleType="fitXY" flexGrow="1" url="${image1}">
            </Image>
            <Text marginTop="5" textAlign="center" textSize="11" text="初音將來">
            </Text>
        </Flex>
        <Flex flexDirection="column" justifyContent="center" marginLeft="3" marginRight="3" flexGrow="1">
            <Image blurSampling="3" blurRadius="25" borderRadius="4" scaleType="fitXY" flexGrow="1" url="${image2}">
            </Image>
            <Text marginTop="5" textAlign="center" textSize="11" text="高斯模糊">
            </Text>
        </Flex>
    </Flex>
</Flex>
複製代碼

3.3 填充數據

數據可由後端生成,正向綁定到模板中去。

{
	"image1": "https://uploadfile.bizhizu.cn/2014/1127/20141127031018144.jpg",
	"isEmpty": 1,
	"name": "tttt",
	"bofang": "100萬",
	"bofangSize": 10,
	"danmu": "10萬",
	"gengduo": "https://s2.ax1x.com/2019/10/11/uqo5tJ.png",
	"image2": "http://5b0988e595225.cdn.sohucs.com/images/20180606/0a49d21848324503a1e04c4b942a1631.png"
}
複製代碼

4 豐富的樣式支持

Gbox支持多種Widget,並有豐富的樣式支持,下面我將一一介紹它們

4.1 通用樣式

每種Widget都支持多種樣式,但有一些樣式是通用的

  • background 能夠是顏色以#開頭或是顏色的名字,或者爲url。能夠調用內置函數「draw:gradient」實現漸變色,以下(最後一個參數是可變參數):
<?xml version="1.0" encoding="utf-8"?>
<Flex width="360" height="600" borderWidth="20" borderRadius="30" borderColor="red" background="${draw:gradient(t2b,red,blue)}">
</Flex>
複製代碼
  • borderRadius 圓角弧度
  • borderWidth 邊框寬度
  • borderColor 邊框顏色
  • alignSelf 本身相對於父組件,如何對齊,支持flexStart,flexEnd,center,baseline,stretch
  • height 高
  • width 寬
  • margin 外邊距
  • marginBottom 外邊距
  • marginTop 外邊距
  • marginLeft 外邊距
  • marginRight 外邊距
  • padding 內邊距
  • paddingTop 內邊距
  • paddingBottom 內邊距
  • paddingLeft 內邊距
  • paddingRight 內邊距
  • clickUrl 一個url,可觸發EventListener的回調
  • reportClick 點擊時上報一個json,此json支持數據綁定,可觸發EventListener的回調
  • reportView 曝光時上報一個json,此json支持數據綁定,可觸發EventListener的回調

4.2 Image

使用Glide做爲圖片加載引擎,支持異步加載、高斯模糊(使用高效的renderscript實現)、圓角裁剪

  • url 圖片來源,一個url
  • blurRadius 高斯模糊的半徑,最大爲25
  • blurSampling 高斯模糊的採樣率,默認爲1
  • borderRadius 有圓角弧度時,會裁剪內部
  • scaleType 縮放類型,有center,fltXY,fitCenter,fitStart,fitEnd,centerInside

4.3 Text

用於顯示文本

  • text 要顯示的文本
  • textAlign 文本對齊,支持center,left,right
  • textSize 文本大小
  • textStyle 文本風格,支持normal,bold
  • maxLines 最大行數
  • minLines 最小行數
  • textColor 字體顏色

4.4 Flex

flex風格的佈局容器

  • flexDirection 佈局的排布方式,支持row,rowReverse,column,columnReverse
  • flexWrap 容器是否包住內部,支持noWrap,wrap,wrapReverse
  • justifyContent 主軸對齊,支持flexStart,flexEnd,center,spaceBetween,spaceAround
  • alignItems 副軸對齊,支持flexStart,flexEnd,center,baseline,stretch
  • alignContent 支持flexStart,flexEnd,center,baseline,stretch

4.5 Scroller

滑動列表實現,與ScrollView等價

  • scrollBarEnable 啓用或關閉scrollBar
  • orientation 水平或者垂直(vertical,horizontal)

4.6 Frame

與FrameLayout相似,可實現多層級疊加

4.7 Embedded

可在佈局中嵌入傳統View

  • type 類名

4.8 for

邏輯標籤,將內部的標籤展開成多組,三個字段都是必填的

  • name 循環中所使用的迭代變量
  • from 開始的下標
  • to 結束的下標
<?xml version="1.0" encoding="utf-8"?>
<Flex height="${height}" >
  <for name="index" from="1" to="3">
    <Text text="${itemTexts[index]}" height="100">
    </Text>
  </for>
</Flex>
複製代碼

等價展開

<?xml version="1.0" encoding="utf-8"?>
<Flex height="${height}" >
    <Text text="${itemTexts[1]}" height="100">
    </Text>
    <Text text="${itemTexts[2]}" height="100">
    </Text>
    <Text text="${itemTexts[3]}" height="100">
    </Text>
</Flex>
複製代碼

4.8 輔助函數

Gbox還包含一些內置函數,能夠在表達式中調用

  • utils:check(o:Any)能夠檢擦一個變量是否有效,爲空或者大小爲0的集合或者爲空的字符串都會返回false值
  • draw:gradient(o:Orientation,vararg colors: String) 用於實現漸變色,第一個參數爲漸變色的方向,有t2b,tr2bl,l2r,br2tl,b2t,r2l,tl2br八種方向可選,第二個參數是可變參,可傳入若干個顏色的字符串

5 如何獲取Gbox ?

5.1 在github上

前往Gbox的github倉庫clone源代碼

5.2 利用jitpack集成

//Add it in your root build.gradle at the end of repositories:
	allprojects {
		repositories {
			...
			maven { url 'https://jitpack.io' }
		}
	}
 
//Add the dependency
    dependencies {
	        implementation 'com.github.LukeXeon.flexbox:core:Tag'
	}
複製代碼

6 開始使用Gbox

6.1 運行測試用例

  • 在手機上安裝overview
  • 確保手機與電腦在同一網絡環境下
  • 運行mock模塊下test文件夾下的MockTestCase(mac上路徑可能會出點問題)
  • 用overview掃描控制檯出現的二維碼,便可開始測試
  • Ctrl+S保存後會刷新手機上的佈局(開啓LiveReload時)

6.2 注意事項

  • Android Studio要換成白色主題,不然生成的二維碼沒法掃描
  • overview 的 LiveReload 開關打開時才能實時預覽佈局,不然只會在掃碼後向電腦拉取一次佈局
  • overview的控制檯會打印佈局上的事件觸發時的log
  • 您可參照mock模塊與overview模塊進行快速集成

7 項目中所使用的開源框架

7.1 mock 模塊

  • google zxing 二維碼
  • google gson json解析

7.2 core 模塊

  • apache el 數據綁定
  • facebook litho 渲染

7.3 overview 模塊

  • squareup retrofit2 網絡請求
  • didi DoraemonKit 輔助工具

8 結語

iOS側和更多功能已經在開發計劃中,敬請關注,也歡迎你來貢獻,咱們將一塊兒開源共建,作出更好的Gbox。

最後的最後仍是慣例啦,若是喜歡個人文章別忘了給我點個贊,拜託了這對我來講真的很重要。若是你以爲東西對你有用的話,也拜託在GitHub上幫忙點個star吧。

相關文章
相關標籤/搜索