如果你进阶的路上缺乏方向,可以加入我们的圈子和安卓开发者们一起学习交流!
-
Android进阶学习全套手册
-
Android对标阿里P7学习视频
-
BATJ大厂Android高频面试题
最后,借用我最喜欢的乔布斯语录,作为本文的结尾:
人这一辈子没法做太多的事情,所以每一件都要做得精彩绝伦。
你的时间有限,所以不要为别人而活。不要被教条所限,不要活在别人的观念里。不要让别人的意见左右自己内心的声音。
最重要的是,勇敢的去追随自己的心灵和直觉,只有自己的心灵和直觉才知道你自己的真实想法,其他一切都是次要。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
现在大家可以看一下自己的项目,找一个你认为布局稍微复杂的界面,然后在开发者选项打开显示过度绘制区域
通过颜色的判断,我们检查对应的布局代码来优化过度绘制问题。
- Tracer for OpenGL ES
针对上面我们看到的过度绘制的区域,我们要想一想应该怎么去优化,但这个时候我们并不太清楚这个过度绘制的区域是怎么形成的,所以我们要借助另外一个工具Tracer for OpenGL ES,它可以记录和分析app每一帧的绘制过程,以及列出所有用到OpenGL ES的绘制函数和耗时,所以通过Tracer for OpenGL ES我们可以很容易的看出app的每一帧是怎么画出来的。
简要使用步骤:
- 连接真机,在AndroidStudio中打开Android Device Monitor,接着Window-> Open Perspective -> Tracer for OpenGL ES。
- 如下图操作,点击捕捉跟踪按钮,然后输入对应的信息,点击跟踪。(华为P10,MI5这两款无法正常跟踪,最后使用的是华为Mate7)
- 点"Stop Tracing"结束,Trace log文件就会生成在预定的目录下。
- 结束后,Trace文件自动打开,如下图介绍,我们点击glDraw函数栏,在右上方看到当前绘制函数所绘制的图像。
我用一个简单的Demo来介绍,我们依次点击glDraw函数栏,可以看到所记录和分析app每一帧的绘制过程。
<?xml version="1.0" encoding="utf-8"?><android.support.design.widget.CoordinatorLayout xmlns:android=“http://schemas.android.com/apk/res/android”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
android:background=“@android:color/white”>
</android.support.design.widget.CoordinatorLayout>
通过刚刚的演示,我们就可以用到了Tracer for OpenGL ES来查找过度绘制的地方来。
小插曲:打开自己mac的AndroidStudio3.1时,竟然一时找不到DDMS,查阅资料发现DDMS在AndroidStudio3.1已经不推荐使用了,只能用回公司AndroidStudio3.0截图,这里为以后的优化工具文章留下一个伏笔。
- Hierarchy Viewer
接着我们介绍一下Hierarchy Viewer,通过它我们可以查找布局不合理的地方,Hierarchy Viewer的使用方法较为简单,AndroidStudio中,同样通过Android Device Monitor,接着Window-> Open Perspective -> Hierarchy Viewer。通过Hierarchy Viewer可以看到我们打开的Activity的UI Tree情况。(注意:我们用模拟器作为例子,先用模拟器运行打开你的应用,再打开Hierarchy Viewer面板。)
拿到UI Tree之后,我们主要分析以下三个问题:(我用一个简单的Demo来分析)
【问题1】没有用的父布局
使用Hierarchy Viewer查看我们的UI Tree,如发现红框的RelativeLayout是CustomTestView唯一子View,我们可以看看是否能把RelativeLayout子View又放到CustomTestView里,这样就可以把RelativeLayout这一层去掉,通过查看代码,我们发现其实RelativeLayout这一层是多余的,我们直接通过merge标签把RelativeLayout和CustomTestView合并.(这种情况在自定义View非常常见)
【问题2】某种情况才会使用的UI被设置成View.GONE 我们在开发应用程序的时候,经常会遇到这种情况,会在运行时动态根据条件来决定显示哪一个View或者ViewGroup,把最先要显示的放在第一位显示,不是第一时间要显示的暂时设置为View.GONE。这样的做法优点是逻辑简单,而且控制起来非常的方便,但是缺点是会消耗资源,虽然把View或者ViewGroup的初始可见设为View.GONE,但是在Inflate布局的时候,View还是被Inflate,也就是说仍然会创建对象,会被实例化,会被设置属性,也就是说会消耗内存等资源的。官方推荐的做法是使用ViewStub,ViewStub是一个轻量级的View,他是一个使用资源非常小的控件。(如果不明白设置成GONE,仍然会消耗资源的同学,可以通过关于View的创建与ViewStub的源码分析进行理解)在我们的代码中,错误页面ErrorView经常会出现这种情况。
【问题3】使用LinearLayout排版导致布局层次加深 从下图可以发现,下面布局是用两个LinearLayout嵌套实现的,但是通过使用一个RelativeLayout我们可以实现同样的效果,这样就可以减少一个层次,从图中可以很明显的看出优化效果。
- 移除或修改Window默认的Background 我们通常在设置通用Theme时候,都用设置一个默认背景色,作为应用的基础色
但是在布局页面,设计人员设计的底色,根本不是默认的背景色,如果我们在这个页面的根布局再设一个背景的话就是多绘制一层背景。
<?xml version="1.0" encoding="utf-8"?>
这种情况,我们可以这样处理:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setBackgroundDrawableResource(android.R.color.white);
setContentView(R.layout.activity_main);
}
这样修改布局的背景色,我们可以避免出现过度绘制的情况。另外上面的设置背景代码,要注意书写顺序,这里可包含了不少View的创建的知识,有兴趣的同学可以自行查阅。
- 减少写View与ViewGroup
- 可以使用RelativeLayout减少层级的就使用RelativeLayout,否则使用LinearLayout线性布局。因为Android中RelativeLayout的测量次数比LinearLayout(不含weight的情况下)多,可以了解一下关于RelativeLayout、LinearLayout、FrameLayout的ViewGroup的测量源码分析。
- 使用SpannableString。相信大家对SpannableString都非常熟悉了,这是一个优化减少书写View的利器。
- 优雅的给LinearLayout、RecyclerView设置分割线。
mRecyclerView.addItemDecoration(new RecyclerView.ItemDecoration() {
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
super.onDraw(c, parent, state);
}
});
强烈不建议,直接在itemView中直接画分割线,虽然是简单,但是我们是一个有追求的开发者,尽量把代码写得漂亮一点。
- 使用merge标签、ViewStub标签、include标签。上面我们都有讲解过。
- drawableLeft 代替ImageView + TextView
- 使用ConstraintLayout。作为AndroidStudio新版本的推荐的默认布局,可想它的强大之处,它是RelativeLayout的加强版,它是百分比布局(已被Deprecated)的替换品。
- %1$d代替TextView + TextView。(如果需要多语言适配你就懂了这的重要性)
这里帮大家整理几个比较经典的注意点,由于有不同层次的读者,所以这里不用具体代码来讲解,如果有不理解的同学,可以单独对某个点进行查阅。
- 代码检测神器——Lint检测工具 估计有一部分同学看完上面的分析讲解之后会觉得,好麻烦呀,要打开这个然后又要那里弄一下。然后就放弃了。接下来这个真的非常适合这部分同学使用。 打开Lint的步骤:Analyze -> Inspect Code -> 选择你需要分析的目录,然后点击确定分析
在Android Lint:Performance这个错误节点下,非常清晰地描述了你都有哪些错误,每一个错误都有非常清晰的描述,你应该如何去改,在右边的箭头,程序帮我们直接定位到错误代码地方,是不是非常方便!
代码逻辑层优化
经过上述的分析调整后,我们接着分析一下关于代码逻辑层的优化。
- Traceview
Traceview是Android设备的一个非常好用的性能分析工具,它可以通过详细的界面,让我们跟踪程序的性能,并且能清晰地查看到每一个函数的耗时和调用次数,所以我们用Traceview的时候要主要两种影响流畅度的原因。一:主线程占用cpu时间很长的方法函数;二:线程调用的次数
我通过具体的应用来具体分析,比如说商城类型的首页,通过是使用RecyclerView,那么我们可以先推断影响RecyclerView的流畅度大多数是RecyclerView.Adapter#onBindViewHolder的方法。
同样是通过Android Device Monitor面板,在下图左方选中需要分析的应用,再点击左上角按钮,当你觉得数据收集足够时,再次点击那个按钮即可,这时Traceview会自动打开trace文件。
那么通过Traceview面板的上部分为时间线面板,左上方面板显示的是采集数据中所采集的线程信息,右边上方面板为时间线,时间线上,每一条线程在采集时间段内所涉及的函数调用信息。而下部分为函数分析面板,是traceview核心界面,它所提供的信息数据非常多,他主要展示了某条线程中各个函数方法调用的情况,包括cpu使用时间,函数方法调用次数,和函数方法真实执行时间等信息,这些信息就是我们分析流畅度的关键所在。
我们了解一下操作,获取方法的调用顺序:
- 在traceview中搜索响应的方法名
- 搜索出的方法会自动展开,其中包含Parents 和 Children 两组信息
- 点击Parents下的方法名,直接跳转到调用当前的方法处。Children则相反
Profile Panel各列功能描述说明
列名 | 描述 |
---|---|
Name | 调用的函数方法名 |
最后
其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。
上面分享的腾讯、头条、阿里、美团、字节跳动等公司2019-2021年的高频面试题,博主还把这些技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,上面只是以图片的形式给大家展示一部分。
【Android思维脑图(技能树)】
知识不体系?这里还有整理出来的Android进阶学习的思维脑图,给大家参考一个方向。
【Android高级架构视频学习资源】
**Android部分精讲视频领取学习后更加是如虎添翼!**进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!