Android性能优化(3)
布局优化
在Android 开发过程中,其实有很大一部分工作量是在写布局上,布局写的好不好,直接影响用户的直观感受。如何做一个运行流畅,可靠,ui美观高效的app,狠重要
渲染
有个帧的概念先说一下,在数字世界,有由一定的帧来模拟真实事物的,有这么一个规律:在单位时间内,越多的帧被处理,我们看到的事物就越真实。10-20/帧/s是大脑感受最小的帧数,低于这个就真的成ptt了。
应用程序的运行过程中帧速率是最理想是60s(不清楚这个数据的出处,书上看到的)也就是说一帧刷新要在1/60s内完成,差不多是16ms的样子,what ???,当然这个再理论值,理想很丰满,现实很骨感,,,,
绘制流程(后来在网上找的,专门补充进来的):
![](https://img.haomeiwen.com/i4923375/716092d3859340ae.png)
附一个链接
Android App卡顿分析,以及使用Choreographer进行帧率统计监测感兴趣的可以看下,互为补充 -_-
一般是做不到的,比如说视图层级嵌套太多导致被重绘的次数太多,占用cpu的太多资源(为什么是cpu,不是都gup了吗???后面会说),如果和出现这种情况,这一帧被丢弃,ui界面不会更新,在下一帧被绘制之前,还是显示之前的图像。我们要做的就是避免此类情况的发生
上图,展示一下在setContentView(int layoutId)的加载过程
![](https://img.haomeiwen.com/i4923375/0981c5ee628732a9.png)
顶层的DecorView,在主题为Activity设置背景,就是通过这玩意来显示的额,其实这个是多余的,这个默认的背景会被设置的布局文件所覆盖,我们要做的就是不让系统做这些无用功
注意
注意
注意
上代码
<resource>
<style name = "Theme.NoBackground" parent = "android.Theme">
<item name = "android:windowBackground">@null</item>
</style>
</resource>
在清单文件里面为Activity设置主题,把上面的代码加上就行了
其实做完这些,你会发现没什么卵用,因为这不会对性能带来明显的改善。但还是建议这么做,性能优化东西,都是量变引起质变的
硬件加速
之前为什么说cup不说gpu了,在Android的版本演进过程中引入了硬件加速,分担一部分cpu的工作,所有视图的渲染以及canvas的绘制,都有gpu来完成,这个是在Android 3.0后引入的
其实现在说这个好像是在说废话,最开始这是一个可选择项,在清单文件里面可以开机硬件加速,但是在Android 4.0之后就默认开启了,不要你操心了。
在引入硬件加速之前,view的属性变化都需要重新绘制,硬件加速可以避免这个问题,因为发生变化的属性并不是view本身,而是图层中的那个对象。这些属性变化不会影响视图的层级结构
- aloha
- x
- y
- translationX
- translationY
- scaleX
- scaleY
- rotationX
- rotationY
- pivotX
- pivotY
看着是不是很熟悉,没错,就是属性动画
提高动画的性能,没说的!!!
上代码
view.setLayerType(View.LAYER_TYPE_HARDWARE,null);
ObjectAnimator animator = ObjectAnimator.ofFloat(view,"rotationY",180);
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
view.setLayerType(View.LAYER_TYPE_NONE,null);
}
});
animator.start();
注意:这个是在Android 6.0之前要干的事,之后就不用了,自适应硬件。这个是要适配低版本的要做的事
点9图片
在Android中,管理位图个管理点9图片的方式是不一样的,系统针对点9图片进行了特殊优化,在点9图片中,被其他视图所遮盖的部分,会被android 渲染成透明的,而透明的像素部分不会被系统渲染,背景图片使用点9图,可以在一定程度上减少过度绘制
布局复用
- include标签
这个标签其实对于开发者来说减少的只不过是Ctrl+C和Ctrl+V的次数而已,对于性能而言并没有多大帮助,依然是有层级的嵌套
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/chat_base_color"
android:orientation="vertical">
<include layout="@layout/account_infor_item"/>
<RelativeLayout
android:id="@+id/title_layout"
android:layout_width="match_parent"
android:layout_height="@dimen/d55"
android:background="@color/base_color"
android:orientation="horizontal">
<ImageView
android:id="@+id/back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_gravity="center_vertical"
android:layout_marginLeft="@dimen/d10"
android:padding="@dimen/d5"
android:src="@mipmap/back" />
<TextView
android:id="@+id/tv_chat_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_gravity="center"
android:layout_marginLeft="@dimen/d10"
android:layout_toRightOf="@id/back"
android:gravity="center"
android:text="@string/name"
android:textColor="@color/white"
android:textSize="@dimen/d20" />
<ImageView
android:id="@+id/tv_chat_edit"
android:layout_width="@dimen/d40"
android:layout_height="@dimen/d40"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="@dimen/d10"
android:scaleType="fitXY"
android:src="@mipmap/group_icon"
android:visibility="gone" />
</RelativeLayout>
</LinearLayout>
就是这样。。。。
- merge标签
但是这个就不一样了,这玩意可以减少布局的允于,整体层级更加扁平,只要将复用布局文件的跟布局换成merge标签就可以了,在加载的时候会忽略掉这个标签,但是,,,,但是,,,,,但是,使用这个标签的时候又两个限制
- 只能作为布局文件的根布局来使用
- 在调用LayoutInflater.inflate()时,必须为merge布局文件提供一个view,作为他的父容器
LayoutInflater.from(context).inflate(R.layout.merge_layout,parent,true)
- viewstub标签
这个就比较厉害了,这东西可以作为一个节点,被添加到布局文件中,它关联着一个布局文件,知道运行时,才会被绘制,
<?xml version="1.0" encoding="utf-8"?>
<ViewStub xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout="@layout/activity_main">
</ViewStub>
上面布局所关联的布局并不会被实例化,直到程序运行期间调用了这些方法
- findviewbyid(R.id.viewstub).setVisibility(View.VISIBLE)
或者
- findviewbyid(R.id.viewstub).inflate()
一旦viewstub变为visible或者被加载,便不可以再用。以为他在布局层级中的位置被实例化出来的布局代替了。
这货很有用,在面对比较复杂的布局层级是,我们可以使用ViewStub延迟部分view的加载,缩短首次加载的时间,减少一些不必要的内存分配。
好了,这篇就到这了,下篇接着再写。。。。。
网友评论