Gbox开源:比RN和WebView更轻的高性能动态化业务容器,解决首页动态化的痛点
总结
秋招即将开始,校招的朋友普遍是缺少项目经历的,所以底层逻辑,基础知识要掌握好!
而一般的社招,更是神仙打架。特别强调,项目经历不可忽视;几乎简历上提到的项目都会被刨根问底,所以项目应用的技术要熟练,底层原理必须清楚。
这里给大家提供一份汇集各大厂面试高频核心考点前端学习资料。涵盖 HTML,CSS,JavaScript,HTTP,TCP协议,浏览器,Vue框架,算法等高频考点238道(含答案)!
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
资料截图 :



高级前端工程师必备资料包

height=“100”>

在上面的布局中,你会发现360这个值会经常出现,没错,在Gbox中它是一个特殊值。为了做屏幕适配,Gbox的大小单位是设备独立的,它以屏幕宽度作为基准,将屏幕宽度分为360份,一个单位的像素值=屏幕宽度像素值/360,这也刚好是2x设计图纸的大小,相信你们的UI设计师会喜欢Gbox的。
Gbox的所有布局属性和层级,最终将被应用到facebook的yoga布局引擎中去,无论布局有多复杂您都不需要担心,因为所有的计算都是在可指定的Layout线程中进行的,根本不会影响主线程,并且最终生成在屏幕上的View是没有这些冗余布局层级的。有关更多Litho的信息,建议您查阅Litho的相关文档。
5.3 Frame
Frame实现了类似Android上FrameLayout的布局效果,用于实现Flex难以实现的多层叠加效果。
在Frame上,Gbox采用了比Flex更激进的布局测量策略。我们都知道,在Android的FrameLayout中onMeasure会去测量所有的子Layout,最终才能确定宽高,Gbox中利用Litho的Component的不可变性(线程安全),将这一操作进行了并行化。

Frame拥有独立的线程池,可以并发地测量所有地子Layout,最终的结果在一个线程汇集,下图演示了该过程。

PS: 说人话就是调用了java.util.concurrent.Executors#newCachedThreadPool,然后等待在一个线程等待其他java.util.concurrent.Future完成,源码链接👉FrameFactory.kt
编写下面的布局实现叠加效果:
<?xml version="1.0" encoding="utf-8"?>
5.4 Image
Image不仅仅只是一张简单的ImageView,它封装了Glide图片加载引擎,支持异步加载、圆角裁剪和高斯模糊。
使用url来加载网络图片:
Gbox没有使用Litho的State来实现异步图片加载,所以不会触发Litho的布局更新,而是直接替换底层的Drawble,然后调用invalidateDrawable,刷新脏矩形。
PS: 说人话就是使用了DrawableWrapper.kt 。
mock所使用的json数据:
{
“image2”: “http://5b0988e595225.cdn.sohucs.com/images/20180606/0a49d21848324503a1e04c4b942a1631.png”
}
编写xml:
<?xml version="1.0" encoding="utf-8"?>

borderRadius存在时,内部的图片会被裁剪:
<?xml version="1.0" encoding="utf-8"?>

使用blurRadius和blurSampling控制高斯模糊:
blurRadius为弧度,值在1-25之间,blurSampling为采样率,值要比1大。
Gbox使用renderscript技术将高斯模糊的效率最大化,能够减少使用高斯模糊时图片出现的延迟时间。
PS: 说人话就是在Glide加载图片的时候加了个Transformation,源码链接👉BlurTransformation.kt


与ImageView一样支持scaleType:
细心的朋友会发现,其实上面已经在使用fitXY了,笑~
<?xml version="1.0" encoding="utf-8"?>

5.5 Text
Text用于显示文本,目前支持一下属性修饰:
- text用于指定要显示的文本
- horizontalGravity用于指定文本对齐方式,支持center、left、right
- textSize用于指定文本大小
- textStyle用于指定文本风格如normal(默认)、bold(粗体)
- maxLines指定最大行数
- minLines指定最小行数
- textColor指定字体颜色

5.6 Native
Gbox对传统业务组件也是友好的。
如果将Gbox接入以后之前写的自定义View都得从头编写的话,那Gbox就失去了快速开发的意义了。所以Gbox也支持原生View的接入。
PS: 说人话就是封装了com.facebook.litho.ViewCompatComponent,源码👉NativeFactory.kt。
使用type属性,编写下面的代码,就能实现下图中所展示的样式。
<?xml version="1.0" encoding="utf-8"?>

值得注意的是Native已经是布局树的叶子节点,这意味着不支持再使用Native包裹其他节点。
5.7 Scroller
Scroller就是ScrollView,与ScrollView一样,它只能有一个子View,它由两个属性控制样式:
- scrollBarEnable是一个布尔值(true或者false)控制是否显示滚动条。
- orientation控制横向还是竖向(vertical或者horizontal)。
【这…这就不展示了吧…我实在是觉得这玩意截图没啥意义…】
5.8 for
当model数据中有列表数据需要展开时,就需要用到for标签。
for标签有三个属性,在使用时都是必须指定的,分别是var,from,to,index用于指定循环中迭代器的名字,from和to则指定了var的的迭代范围。 比如你有下面的数据:
{
“height”:1000,
“itemTexts”:[“Gbox”,“Facebook”,“Litho”,“Google”]
}
编写下面的布局:
<?xml version="1.0" encoding="utf-8"?>
可以被等价展开成:

for标签var所指定的迭代器只会在for循环所包括的布局标签中生效
PS: for标签是调用了Tomcat EL的ELContext#enterLambdaScope和ELContext#exitLambdaScope实现的,代码我就不在这里贴了,你可以👉直接跳转到github看源码
5.9 内置函数
目前Gbox还支持一些内置函数,内置函数必须在绑定表达式中才能调用:
utils:check(o:Any)
可以检测一个变量是否有效,为空或者大小为0的集合或者为空的字符串都会返回false值
check方法是由kotlin实现的:
fun check(o: Any?): Boolean {
return when (o) {
is String -> o.isNotEmpty()
is Collection<*> -> !o.isEmpty()
is Number -> o.toInt() != 0
else -> o != null
}
}
在下面的布局逻辑中,屏幕上不会展示任何东西,因为json中没有’no_found’这个变量。
<?xml version="1.0" encoding="utf-8"?>draw:gradient(o:Orientation,vararg colors: String)
用于实现渐变色,第一个参数为渐变色的方向,有t2b(上到下),tr2bl(上右到下左),l2r(右到左),br2tl(下右到上左),b2t(下到上),r2l(右到左),tl2br(上左到下右)八种方向可选,第二个参数是可变参,可传入若干个颜色的字符串
kotlin的源码实现:
fun gradient(orientation: GradientDrawable.Orientation, vararg colors: String): GradientDrawable {
return GradientDrawable(orientation, colors.map {
parseColor(it)
}.toIntArray())
}
编写xml实现渐变色:
<?xml version="1.0" encoding="utf-8"?>
5.10 其他通用属性
除了上述属性之外还有很多属性是通用的,受限于篇幅,这里我对一些比较重要的属性进行简单介绍。
background属性是对所有Widget都通用的,用于为图片指定背景,它支持以下三种显示来源:
- 图片的url
- 以#开头的十六进制颜色值
- 渐变色(上面已经演示过了)
以图片url为背景
<?xml version="1.0" encoding="utf-8"?>
borderRadius 用于实现裁剪背景边界的圆角。
<?xml version="1.0" encoding="utf-8"?>
你还可以使用borderColor和borderWidth为边界指定宽度和颜色。
<?xml version="1.0" encoding="utf-8"?>
使用clickUrl并打开overview APP的控制台,点击图片,就能在EventListener中收到点击事件传递下来的信息,它可以是一个url,供外部跳转使用。
<?xml version="1.0" encoding="utf-8"?>
于此类似的属性还有reportView(曝光时上报),reportClick(点击时上报)都可以在控制台查看。
还有一些通用属性,我也在这里也简单列了一下:
宽高
- height
- width
可见性
- visibility 与Android类似,支持visible、invisible和gone
外边距
- margin
- marginBottom
- marginTop
- marginLeft
- marginRight
内边距
- padding
- paddingTop
- paddingBottom
- paddingLeft
- paddingRight
Flexbox所支持的其他属性
- alignSelf
- alignContent
- flexGrow
- flexShrink
- …
对于Flexbox这部分,我真诚地推荐你去看阮一峰老师的文章Flex布局教程。
Gbox中的对应属性基本上就是将这些属性使用java的命名风格,取消中位线,第二个单词开始使用大写。如在css中的align-content在Gbox中就是alignContent。
6 后端集成注意事项
6.1 集成建议
在后端,可能集成者需要建立一个统一的布局管理系统,包括:
- 布局cdn。
- git联动的版本控制功能等等。
当然这些也在未来的开发计划中,欢迎您的PR。
6.2 下发的是json不是xml
值得注意的是,虽然编写布局使用的是xml,但是您可以发现最终mock服务器下发到客户端的只有json,这是因为在下发布局时mock服务器已经将xml转换为了json,这样做的目的是为了布局集成到数据接口中下发,使用统一工具进行解析,所以Gbox没有耦合xml的解析模块,而是最大化的利用了现有基础设施。所以在后端集成时需要把xml转换为json来保存。
7 在新项目中集成Gbox
7.1 远程依赖Gbox
Gbox使用jitpack进行构建,在你的根项目的build.gradle中添加
allprojects {
repositories {
…
maven { url ‘https://jitpack.io’ }
}
}
然后在模块中依赖
dependencies {
implementation ‘com.github.LukeXeon.flexbox:core:latest.release’
}
Sync项目,即可将SDK集成到项目中,Gbox的包大小不算太大,约为1M左右,这其中主要是Facebook的Litho的大小。
7.2 集成Gbox的容器Litho
Gbox基于Litho,所以你还得先找个地方初始化Litho,可以是Application,或者第一个Activity里,反正用LithoView之前初始化就行了。
SoLoader.init(this, false);
LithoView是Gbox的容器,在xml中使用:
<com.facebook.litho.LithoView
android:id=“@+id/host”
android:layout_width=“match_parent”
android:layout_height=“match_parent”>
</com.facebook.litho.LithoView>
然后在Java层中拿到实例,调用setComponentAsync方法,传入一个新构造的DynamicBox。
mLithoView.setComponentAsync(
DynamicBox.create©
.bind(data)
.layout(layout)
.eventListener(this)
.build()
);
其中layout是一个com.guet.flexbox.NodeInfo类的实例,它用来描述一颗布局树,是整棵布局树的树根。
而data则是绑定到布局中的数据,它支持多种数据格式自动匹配,分为以下两种情况:
- 在项目中依赖了Gson的情况下,data可以直接是String、byte[]、Reader、InputStream这些数据源。
- 如果项目中没有Gson,那么Gbox也支持嵌套的多层级Map<String,Object>以及标准的java bean(有getter,setter)作为数据源。
在overview APP中,我使用了Retrofit来简化了这一过程。
添加Retrofit的依赖:
implementation ‘com.squareup.retrofit2:retrofit:2.6.2’
implementation ‘com.squareup.retrofit2:converter-gson:2.6.2’
用Retrofit实例化接口:
package com.guet.flexbox.overview;
import com.guet.flexbox.NodeInfo;
import java.util.Map;
import retrofit2.Call;
import retrofit2.http.GET;
public interface MockService {
@GET(“/data”)
Call<Map<String, Object>> data();
@GET(“/layout”)
Call layout();
}
mMockService = new Retrofit.Builder()
.baseUrl(url)
.client(new OkHttpClient())
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(MockService.class);
EventListener用来处理事件回调,目前有三种事件点击、上报点击和上报曝光。
package com.guet.flexbox
enum class EventType {
CLICK,
REPORT_CLICK,
REPORT_VIEW
}
package com.guet.flexbox
总结
-
框架原理真的深入某一部分具体的代码和实现方式时,要多注意到细节,不要只能写出一个框架。
-
算法方面很薄弱的,最好多刷一刷,不然影响你的工资和成功率😯
-
在投递简历之前,最好通过各种渠道找到公司内部的人,先提前了解业务,也可以帮助后期优秀 offer 的决策。
-
要勇于说不,对于某些 offer 待遇不满意、业务不喜欢,应该相信自己,不要因为当下没有更好的 offer 而投降,一份工作短则一年长则 N 年,为了幸福生活要慎重选择!!!

喜欢这篇文章文章的小伙伴们点赞+转发支持,你们的支持是我最大的动力!
ervice.class);
EventListener用来处理事件回调,目前有三种事件点击、上报点击和上报曝光。
package com.guet.flexbox
enum class EventType {
CLICK,
REPORT_CLICK,
REPORT_VIEW
}
package com.guet.flexbox
总结
-
框架原理真的深入某一部分具体的代码和实现方式时,要多注意到细节,不要只能写出一个框架。
-
算法方面很薄弱的,最好多刷一刷,不然影响你的工资和成功率😯
-
在投递简历之前,最好通过各种渠道找到公司内部的人,先提前了解业务,也可以帮助后期优秀 offer 的决策。
-
要勇于说不,对于某些 offer 待遇不满意、业务不喜欢,应该相信自己,不要因为当下没有更好的 offer 而投降,一份工作短则一年长则 N 年,为了幸福生活要慎重选择!!!

喜欢这篇文章文章的小伙伴们点赞+转发支持,你们的支持是我最大的动力!
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)