view = mFactory2.onCreateView(parent, name, context, attrs);
} else if (mFactory != null) {
view = mFactory.onCreateView(name, context, attrs);
} else {
view = null;
}
…
return view;
}
在真正进行反射实例化xml
结点前,会调用mFactory2
的onCreateView
方法
这样如果我们重写onCreateView
方法,在其前后加上耗时统计,即可获取每个控件的加载耗时
private fun initItemInflateListener(){
LayoutInflaterCompat.setFactory2(layoutInflater, object : Factory2 {
override fun onCreateView(
parent: View?,
name: String,
context: Context,
attrs: AttributeSet
): View? {
val time = System.currentTimeMillis()
val view = delegate.createView(parent, name, context, attrs)
Log.i(“inflate Item”,name + " cost " + (System.currentTimeMillis() - time))
return view
}
override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? {
return null
}
})
}
如上所示:真正的创建View
的方法,仍然是调用delegate.createView
,我们只是其之前与之后做了埋点
注意,initItemInflateListener
需要在onCreate
之前调用
这样就可以比较方便地实现监听每个控件的加载耗时
布局加载慢的主要原因有两个,一个是IO
,一个是反射
所以我们的优化思路一般有两个
1.侧面缓解(异步加载)
2.根本解决(不需要IO
,反射过程,如X2C
,Anko
,Compose
等)
AsyncLayoutInflater
方案
AsyncLayoutInflater
是来帮助做异步加载layout
的,inflate(int, ViewGroup, OnInflateFinishedListener)
方法运行结束之后OnInflateFinishedListener
会在主线程回调返回View
;这样做旨在UI
的懒加载或者对用户操作的高响应。
简单的说我们知道默认情况下 setContentView
函数是在 UI
线程执行的,其中有一系列的耗时动作:Xml
的解析、View
的反射创建等过程同样是在UI
线程执行的,AsyncLayoutInflater
就是来帮我们把这些过程以异步的方式执行,保持UI
线程的高响应。
使用如下:
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new AsyncLayoutInflater(AsyncLayoutActivity.this)
.inflate(R.layout.async_layout, null, new AsyncLayoutInflater.OnInflateFinishedListener() {
@Override
public void onInflateFinished(View view, int resid, ViewGroup parent) {
setContentView(view);
}
});
// 别的操作
}
这样做的优点在于将UI
加载过程迁移到了子线程,保证了UI
线程的高响应
缺点在于牺牲了易用性,同时如果在初始化过程中调用了UI
可能会导致崩溃
X2C
方案
X2C
是掌阅开源的一套布局加载框架
它的主要是思路是在编译期,将需要翻译的layout翻译生成对应的java文件,这样对于开发人员来说写布局还是写原来的xml,但对于程序来说,运行时加载的是对应的java文件。
这就将运行时的开销转移到了编译时
如下所示,原始xml文件:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:app=“http://schemas.android.com/apk/res-auto”
xmlns:tools=“http://schemas.android.com/tools”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
android:paddingLeft=“10dp”>
<include
android:id=“@+id/head”
layout=“@layout/head”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
android:layout_centerHorizontal=“true” />
<ImageView
android:id=“@+id/ccc”
style=“@style/bb”
android:layout_below=“@id/head” />
X2C
生成的 Java
文件
public class X2C_2131296281_Activity_Main implements IViewCreator {
@Override
public View createView(Context ctx, int layoutId) {
Resources res = ctx.getResources();
RelativeLayout relativeLayout0 = new RelativeLayout(ctx);
relativeLayout0.setPadding((int)(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,10,res.getDisplayMetrics())),0,0,0);
View view1 =(View) new X2C_2131296283_Head().createView(ctx,0);
RelativeLayout.LayoutParams layoutParam1 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
view1.setLayoutParams(layoutParam1);
relativeLayout0.addView(view1);
view1.setId(R.id.head);
layoutParam1.addRule(RelativeLayout.CENTER_HORIZONTAL,RelativeLayout.TRUE);
ImageView imageView2 = new ImageView(ctx);
RelativeLayout.LayoutParams layoutParam2 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,(int)(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,1,res.getDisplayMetrics())));
imageView2.setLayoutParams(layoutParam2);
relativeLayout0.addView(imageView2);
imageView2.setId(R.id.ccc);
layoutParam2.addRule(RelativeLayout.BELOW,R.id.head);
return relativeLayout0;
}
}
使用时如下所示,使用X2C.setContentView
替代原始的setContentView即可
// this.setContentView(R.layout.activity_main);
X2C.setContentView(this, R.layout.activity_main);
X2C
优点
1.在保留xml
的同时,又解决了它带来的性能问题
2.据X2C
统计,加载耗时可以缩小到原来的1/3
X2C
问题
1.部分属性不能通过代码设置,Java
不兼容
2.将加载时间转移到了编译期,增加了编译期耗时
3.不支持kotlin-android-extensions
插件,牺牲了部分易用性
Anko
方案
Anko
是JetBrains
开发的一个强大的库,支持使用kotlin DSL
的方式来写UI
,如下所示
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
MyActivityUI().setContentView(this)
}
}
class MyActivityUI : AnkoComponent {
override fun createView(ui: AnkoContext) = with(ui) {
verticalLayout {
val name = editText()
button(“Say Hello”) {
onClick { ctx.toast(“Hello, ${name.text}!”) }
}
}
}
}
如上所示,Anko
使用kotlin DSL
实现布局,它比我们使用Java
动态创建布局方便很多,主要是更简洁,它和拥有xml
创建布局的层级关系,能让我们更容易阅读
同时,它去除了IO
与反射过程,性能更好,以下是Anko
与XML
的性能对比
不过由于AnKo
已经停止维护了,这里不建议大家使用,了解原理即可
AnKo
建议大家使用Jetpack Compose
来替代使用
Compose
方案
Compose
是 Jetpack
中的一个新成员,是 Android
团队在2019年I/O
大会上公布的新的UI
库,目前处于Beta
阶段
Compose
使用纯kotlin
开发,使用简洁方便,但它并不是像Anko
一样对ViewGroup
的封装
Compose
并不是对 View
和 ViewGroup
这套系统做了个上层包装来让写法更简单,而是完全抛弃了这套系统,自己把整个的渲染机制从里到外做了个全新的。
可以确定的是,Compose
是取代XML
的官方方案
Compose
的主要优点就在于它的简单好用,具体来说就是两点
1.它的声明式 UI
2.去掉了 xml
,只使用 Kotlin
一种语言
由于本文并不是介绍Compose
的,所以就不继续介绍Compose
了,总得来说,Compose
是未来android UI
开发的方向,读者可以自行查阅相关资料
上面介绍了不少布局加载优化方法,而我最后在项目中最后都没有使用,这就是从真从入门到放弃
总得来说有以下几个原因
1.有些方式(如AsyncLayoutInflater
,X2C
)牺牲了易用性,虽然性能提升了,但是开发变得麻烦了
2.Anko
使用上比较方便同时性能较高,但是比起XML
方式改动很大,同时Anko
已经放弃维护了,在团队中推动难度大
3.Compose
是未来android UI
开发的方向,但目前仍处于Beta
阶段,相信在Release
后,会成为我们替换XML
的有效手段
4.还有最主要的一点是,针对我们的项目,布局加载耗时并不是主要耗时的地方,所以优化收益不大,可以将精力投入到其他地方
如下所示,我们将setConteView
前后时间相减,得到布局加载时间
而onWindowFocusChanged
是Activity
真正可见时间,将其与onCreate
时间相减,可得页面显示时间
在我们的项目中测试效果如下:
android 5.0
I/Log: inflateTime:33
I/Log: activityShowTime:252
I/Log: inflateTime:11
I/Log: activityShowTime:642
I/Log: inflateTime:83
I/Log: activityShowTime:637
android 10.0
I/Log: inflateTime:11
I/Log: activityShowTime:88
I/Log: inflateTime:5
I/Log: activityShowTime:217
I/Log: inflateTime:27
I/Log: activityShowTime:221
我在android
5.0手机与10.0手机上分别做了测试,在我们的项目中布局加载耗时并不很长,同时它们在整个页面可见过程中,占得比例也并不高
所以得出结论:针对我们项目,布局加载耗时并不是主要耗时的地方,优化收益不大
这就是从入门到放弃的原因
一些常规优化手段
上面介绍了一些改动比较大的方案,其实我们在实际开发中也有些常规的方法可以优化布局加载
比如优化布局层级,避免过度绘制等,这些简单的手段可能正是可以应用到项目中的
优化布局层级及复杂度
1.使用ConstraintLayout
,可以实现完全扁平化的布局,减少层级
2.RelativeLayout
本身尽量不要嵌套使用
3.嵌套的LinearLayout
中,尽量不要使用weight
,因为weight
会重新测量两次
4.推荐使用merge
标签,可以减少一个层级
5.使用ViewStub
延迟加载
避免过度绘制
1.去掉多余背景色,减少复杂shape
的使用
2.避免层级叠加
3.自定义View
使用clipRect
屏蔽被遮盖View
绘制
本文主要介绍了以下内容
1.andrid
绘制原理与布局加载原理
2.如何定量的获取android
布局加载耗时
3.介绍了一些布局加载优化的方法与手段(AsyncLayoutInflater
,X2C
,Anko
,Compose
等)
4.介绍了因为在我们在项目中布局加载耗时优化收益不大,所以没有引入上述优化手段
最后分享给大家一份阿里P8大佬熬夜30天整理的《Android 360°全方面性能调优》,涵盖设计思想与代码质量优化、程序性能优化、开发效率优化、其中详细讲解了启动优化、布局优化、内存优化、屏幕适配、OOM问题等方面,并且他还将自己工作中的一些项目案例在PDF中做了实践分享,整合成了一套系统的性能优化知识笔记PDF,长达721页,几乎都可以出本书了。
第一章:设计思想与代码质量优化
1.六大原则.
2.设计模式
3.数据结构
4.算法
第二章:程序员性能优化
1.启动速度与执行效率优化
2.布局检测与优化
3.内存优化
4.耗电优化
5.网络传输与数据储存优化
6.APK大小优化
7.屏幕适配
8.OOM问题原理解析
9.ANR问题解析
10.Crash监控方案
第三章:开发效率优化
1.分布式版本控制系统Git
2.自动化构建系统Gradle
第四章:APP性能优化实践
1.启动速度
2.流畅度
3.抖音在APK包大小资源优化的实践
4.优酷响应式布局技术全解析
5.网络优化
6.手机淘宝双十一性能优化项目揭秘
7.高德APP全链路源码依赖分析
先自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以扫码领取!!!!
![](https://img-blog.csdnimg.cn/img_convert/c4784ac5e8485f745e9f36d105c97863.jpeg)
最后
我一直以来都有整理练习大厂面试题的习惯,有随时跳出舒服圈的准备,也许求职者已经很满意现在的工作,薪酬,觉得习惯而且安逸。
不过如果公司突然倒闭,或者部门被裁减,还能找到这样或者更好的工作吗?
我建议各位,多刷刷面试题,知道最新的技术,每三个月可以去面试一两家公司,因为你已经有不错的工作了,所以可以带着轻松的心态去面试,同时也可以增加面试的经验。
我可以将最近整理的一线互联网公司面试真题+解析分享给大家,大概花了三个月的时间整理2246页,帮助大家学习进步。
由于篇幅限制,文档的详解资料太全面,细节内容太多,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!以下是部分内容截图:
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可免费领取!
部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频**
如果你觉得这些内容对你有帮助,可以扫码领取!!!!
![](https://img-blog.csdnimg.cn/img_convert/c4784ac5e8485f745e9f36d105c97863.jpeg)
最后
我一直以来都有整理练习大厂面试题的习惯,有随时跳出舒服圈的准备,也许求职者已经很满意现在的工作,薪酬,觉得习惯而且安逸。
不过如果公司突然倒闭,或者部门被裁减,还能找到这样或者更好的工作吗?
我建议各位,多刷刷面试题,知道最新的技术,每三个月可以去面试一两家公司,因为你已经有不错的工作了,所以可以带着轻松的心态去面试,同时也可以增加面试的经验。
我可以将最近整理的一线互联网公司面试真题+解析分享给大家,大概花了三个月的时间整理2246页,帮助大家学习进步。
由于篇幅限制,文档的详解资料太全面,细节内容太多,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!以下是部分内容截图:
[外链图片转存中…(img-x44D711V-1711252690317)]
[外链图片转存中…(img-oCE2AFPs-1711252690318)]
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可免费领取!