Facebook YOGA初探:跨平台的布局引擎(基于Android)

YOGA简介

Facebook引领着移动开源风向,这次它对布局出手了,推出了Yoga开源项目,意在打造一个跨iOS、Android、Windows平台在内的布局引擎,兼容Flexbox布局方式,让界面布局更加简单。

Yoga官网:https://facebook.github.io/yoga/

官网上描述的特性包括:

  • 完全兼容Flexbox布局,遵守W3C的规范

  • 支持Java、C#、Objective-C、C四种语言

  • 底层代码使用C语言编写,性能不是问题

  • 支持流行框架如React Native

背景

目前,各个平台都有自己的一套解决方案。iOS平台有AutoLayout,Android有容器布局系统,而Web端有基于CSS的布局系统。多种布局系统共存所带来的弊端是很明显的,平台间的共享变得很困难,而每个平台都需要专人来开发维护,增加了开发成本。

像微信小程序、ReactNative这种,都是采用js/html/css开发,客户端native展现的方式,那如何把前端的布局对应到Android/iOS的不同平台上?

微信小程序、ReactNative都是怎么来实现的?

YOGA就是为了解决这样的问题产生的。

在React Native里Facebook里引入了一种跨平台的基于CSS的布局系统,它实现了Flexbox规范。基于这个布局系统,不同团队终于可以走到一起,一起解决缺陷,改进性能,让这个系统更加地贴合Flexbox规范。随着这个系统的不断完善,Facebook决定对它进行重启发布,并取名Yoga。

Yoga是基于C实现的。之所以选择C,首先当然是从性能方面考虑的。基于C实现的Yoga比之前Java实现在性能上提升了33%。其次,使用C实现可以更容易地跟其它平台集成。到目前为止,Yoga已经有以下几个平台的绑定:Java(Android)、Objective-C(UIKit)、C#(.NET)。而且已经有很多项目在使用Yoga,比如React Native、Components for Android、Oculus,等等。

不同于其它的一些布局框架,比如bootstrap的栅格系统或Masonry,它们要么不够强大,要么不支持跨平台。Yoga遵循了Flexbox规范,同时又将布局元素抽象成Node,为各个不同平台暴露出一组标准的接口,这样不同的平台只需实现这些接口就可以了。

当然,Facebook不会就此止步。作为一款跨平台的布局引擎,自然需要各个平台的开发人员一起努力来促进它的发展,所以Facebook把Yoga开源了。目前微软已经成为Yoga的贡献者之一,他们不仅修复缺陷,还为Yoga带来新的特性。

除了完全遵循Flexbox规范,Facebook还计划在未来为Yoga加入更多特性,这些特性将超出Flexbox的范畴。

应用展望

从目前为止,困扰客户端的一大问题就是Android/iOS完全不同的布局系统,对于Android来说复杂的布局必须使用xml来描述,而xml不能动态发布的特性,也完全限制了客户端view的展现,试想一下,如果能把Android/iOS的布局统一,并且可以根据下发的布局配置实时生成动态的布局,岂不是很爽!

利用YOGA我们可以

  • 只写一次布局,就可以得到在不同端上的布局展示。
  • 动态更改view的布局
  • 还有各种意义。。。

总的来说,大前端的趋势越发明显

YOGA初探

当得知YOGA开源的消息时,楼主第一时间去github上看了源代码,Facebook提供了iOS和Windows的sample工程,唯独没有提供Android的example,只有一个Java库的代码,于是楼主在想既然源码都有,那写一个Android的example,于是就动起手来,最后终于把YOGA集成在了Android的工程上,并顺利跑通。具体过程如下。

生成so

YOGA是基于C实现的,因此我们的思路很明确,就是把YOGA的C代码交叉编译成可在
Android上运行的so。这里我们需要用到BUCK,因为YOGA是基于BUCK构建的,BUCK可以理解成是和Gradle一样的构建工具,这里有一个关于Gradle和Buck的构建速度对图:

要得到android-armv7的so,需要交叉编译,我们需要确保本地已经安装了Android NDK的环境,可以参考Android 官网

通过分析YOGA工程的BUCK配置,发现YOGA由3个模块组成,分布在三个地方,分别是:

  • libyogacore.so 在/yoga目录下
  • libyouga.so 在/java/jni目录下
  • liblib_fb_fbjni.so 在/lib/fb 目录下

我们只要执行BUCK的构建代码,就可以生成上面提到的三个so,构建代码如下:

$ buck build //java:jni#android-armv7,shared

这里有坑,编译时我们需要两个flavor,分别是android-armv7shared

  • android-armv7 就是支持armeabi架构的.so文件,这里需要有NDK环境的支持
  • shared 就是生成动态链接库

因为,如果我们直接使用默认的构建配置

$ buck build

会发现,生成的不是动态链接库so,而是静态链接库,而且也不是基于android-armv7生成的so,所以需要指定编译的platform和明确要编译的是动态链接库,才能生成可用的so.

当完成上面的步骤之后,我们还会发现一个问题,就是当你的工程在加载so的时候,会报错:

can't find  libgnustl_shared.so 

这时我们需要把ndk目录下的 libgnustl_shared.so 也拷贝到工程目录下,路径如下:

android-ndk-r13b/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi-v7a

为什么会有这样的

创建Android工程

在生成so之后,后面的步骤大家应该很清楚了,把生成的so放在Android目录下的jniLibs下,并把YOGA中的java库引入工程,一个完整的可以运行YOGA的Android工程就创建好了。

sample

目前写了一个很简单的用YOGA实现的布局,首先我们用基于Flexbox的规范来布局view,然后调用root.calculateLayout() 就可以得到在Android下的view的坐标、长、宽等基本布局信息,代码如下:

            YogaNode root = new YogaNode();
            root.setWidth(500);
            root.setHeight(300);
            root.setAlignItems(YogaAlign.CENTER);
            root.setJustifyContent(YogaJustify.CENTER);
            root.setPadding(YogaEdge.ALL, 20);

            YogaNode text = new YogaNode();
            text.setWidth(200);
            text.setHeight(25);

            YogaNode image = new YogaNode();
            image.setWidth(50);
            image.setHeight(50);
            image.setPositionType(YogaPositionType.ABSOLUTE);
            image.setPosition(YogaEdge.END, 20);
            image.setPosition(YogaEdge.TOP, 20);

            root.addChildAt(text, 0);
            root.addChildAt(image, 1);

            root.calculateLayout();

            Log.d(TAG,"text,layout X:"+text.getLayoutX()+" layout Y:"+text.getLayoutY());
            Log.d(TAG,"image,layout X:"+image.getLayoutX()+" layout Y:"+image.getLayoutY());

工程

目前我把基于YOGA的Android工程已传到github,欢迎各位多多交流,多给star。Thanks!
地址:https://github.com/koudle/AndYogaSample

文章参考:

https://facebook.github.io/yoga/
https://buckbuild.com/
http://mp.weixin.qq.com/s/VT6uytG8di-KNfJDCZE5Og

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,511评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,495评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,595评论 0 225
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,558评论 0 190
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,715评论 3 270
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,672评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,112评论 2 291
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,837评论 0 181
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,417评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,928评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,316评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,773评论 2 234
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,253评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,827评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,440评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,523评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,583评论 2 249

推荐阅读更多精彩内容