android性能优化

1、布局的优化
include布局

解决问题:当多个页面引用同一个布局时,可以先将这部分布局定义为一个单独的XML,然后在需要的地方通过引入

<RelativeLayout android:layout_width="fill_parent"          android:layout_height="fill_parent"  
    xmlns:android="http://schemas.android.com/apk/res/android"> 
    <!-- include标签内不能设置RelativeLayout属性,如android:layout_alignParentBottom,因为不起作用 -->  
    <!-- include标签内设置id属性后(android:id),其引用的布局layout内的id属性就不起作用了,怀疑是其引用的layout外层包裹了一层include标签   
        或者是覆盖了其内的属性id-->  
    <!-- 如果没有include标签,所有布局代码都写在一个xml文件中,界面会显得很冗余,可读性很差。而且界面加载的时候是按照顺序加载的,前面的布局不能  
        调用其后面的布局id。而采用include后,一个include中可以引用其后的include中的布局id属性 -->  
    <include android:id="@id/title" layout="@layout/app_title" />  
</RelativeLayout> 

merge标签

这里写图片描述
图1

解决的问题当子布局的根视图与它的父视图是同一类型的,如图1所示

<?xml version="1.0" encoding="utf-8"?>  
<merge xmlns:android="http://schemas.android.com/apk/res/android"  
              android:layout_width="match_parent"  
              android:layout_height="wrap_content"  
              android:orientation="horizontal">  

    <Button 
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"/>  

    <ImageView  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"/>  
</merge>  

viewStub布局

viewStub是一个不可见且能在运行期间延迟加载目标视图的高和宽都为0的view

解决的问题

在开发应用程序的时候,经常会遇到这样的情况,会在运行时动态根据条件来决定显示哪个View或某个布局。那么最通常的想法就是把可能用到的View都写在上面,先把它们的可见性都设为View.GONE,然后在代码中动态的更改它的可见性。这样的做法的优点是逻辑简单而且控制起来比较灵活。但是它的缺点就是,耗费资源。虽然把View的初始可见View.GONE但是在Inflate布局的时候View仍然会被Inflate,也就是说仍然会创建对象,会被实例化,会被设置属性。也就是说,会耗费内存等资源
viewStub能减少上述情况的资源耗费
viewStub特点:
1. ViewStub只能Inflate一次,之后ViewStub对象会被置为空。按句话说,某个被ViewStub指定的布局被Inflate后,就不会够再通过ViewStub来控制它了。
2. ViewStub只能用来Inflate一个布局文件,而不是某个具体的View,当然也可以把View写在某个布局文件中。

使用viewStub
1、添加viewStub到xml文件中

 <ViewStub   
    android:id="@+id/viewstub_demo_image"  
    android:layout_width="wrap_content"  
    android:layout_height="wrap_content"  
    android:layout_marginLeft="5dip"  
    android:layout_marginRight="5dip"  
    android:layout="@layout/viewstub_layout"/>  

2、在java代码中使用viewStub
调用inflate()或者setVisiblity(View.VISIBLE)才加载viewstub_layout布局

ViewStub stub = (ViewStub) findViewById(R.id.viewstub_text);  
 stub.inflate();  
 //stub.setVisiblity(View.VISIBLE)
 TextView text = (TextView) findViewById(R.id.viewstub_textview);  
 text.setText("");  

总结:布局优化的时候,尽量减少视图的层级,每个是视图在显示的时候都会经历测量、布局、绘制的过程,如果嵌套过多会造成额外的布局和绘制的过程,使得UI会变的卡顿,影响用户体验

2、内存的优化
GC机制:是什么,移除不可达的对象
使用Serivce的时候:
当这个Service已经完成任务后停止Service失败导致的OOM
解决方法:
1、使用IntentService,因为它会在处理完任务后,尽快的结束自己
UI隐藏时释放内存
当UI不可见时,应该释放UI上所占用的所有资源,可以提高用户体验
解决方法:
为了接收用户离开UI的通知,需要实现Activity类中onTrimMemory()的回调

其他内存的优化:

内存紧张时释放部分内存
检查应该使用多少内存
避免Bitmap的浪费
使用优化的数据容器
注意内存开销
注意代码抽象
为序列化数据使用nano protobufs
避免使用依赖注入框架
谨慎使用外部库
优化整体性能
使用ProGuard来剔除不必要的代码
对最终APK使用Zipalign
使用多进程

3、内存泄漏(OOM)
内存泄漏
(不可达的对象集中在堆内存中,占用内存空间)
内存溢出–>Crash
GC操作
使用 Memory Monitor工具收集GC操作的信息
简介:

它是一个实时的获取应用的内存使用情况的工具

使用Heap工具收集GC操作的信息
简介

Heap通过显示系统为你分配的多少内存来帮助你诊断内存泄漏
这些信息包括App内分配的各种对象、分配对象的数量以及这些对象占用了多少空间
内存泄漏检测器LeakCanary
Square 2015年5月的开源项目,它的作用是自动追踪内存泄漏问题
解决了MAT需要分析复杂的数据,然后一步一步的定位问题所在的问题

下面是ReadMe中的内容
这里写图片描述

Getting started

In your build.gradle:

dependencies {
debugCompile ‘com.squareup.leakcanary:leakcanary-android:1.5.1’
releaseCompile ‘com.squareup.leakcanary:leakcanary-android-no-op:1.5.1’
testCompile ‘com.squareup.leakcanary:leakcanary-android-no-op:1.5.1’
}
In your Application class:

public class ExampleApplication extends Application {
private static RefWatcher mRefWatcher;
@Override public void onCreate() {
super.onCreate();
LeakCanary.install(this);
}

public static RefWatcher getRefWatcher(){
return mRefWatcher;
}
}


API 14(android 40)以上增加了AcitivityLifecycleCallbacks,通过者个回调能监控Activity的生命周期。
注意:android4.0以下没有AcitivityLifecycleCallbacks,可以手动添加Activity监控
即在Activity的onDestory方法中调用RefWatcher的watch方法
4、性能优化
过度绘制
问题描述:

在屏幕一个像素上绘制多次(超过一次)。比如一个TextView后有背景,那么显示文本的像素至少绘了两次,一次是背景,一次是文本。这种情况可能造成用户界面卡顿

监测过度绘制:

android设备内置了监测过度绘制的工具
打开设置—》开发者选项—》调试GPU过度绘制(Debug GPU Overdraw)—->显示过度绘制区域(show overdraw area)
颜色标识: GPU过渡绘制从好到差:蓝-绿-淡红-红
没有颜色:没有过度绘制
蓝色1x过度绘制
绿色2x过度绘制
淡红色3x过度绘制
红色超过4x过度绘制

最小化过度绘制:

1、打开过度重叠的区域的XML,特别是不可见的drawble和绘制在其他控件的背景,还有布局背景是白色其父视图的背景也是白色的
实例:
一般在Activity中,如果使用到了
setContentView(R.layout.XXX);
一般都会存在至少两层的绘制,一层是窗口window的绘制,一层是布局的背景(如果存在背景的话)。如果是这种情况,可以将这个window背景去掉,这个背景的重绘是系统级别的,和主题有关。
解决:
Tthis.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
去除窗口的绘制即可。
2、android 系统自动降低简单的过度绘制,但对于自定义view没有什么价值,
如果是这种情况,可以使用clipRect函数为该视图定义可绘制的区域的边界
更多信息参考android官方文档

android图形渲染
android渲染每个视图分为三个阶段:测量、布局、绘制
父视图发现任意尺寸问题,都会强制要求所有的子视图重新测量
Relativelayout会对它的子视图进行两次测量,LinearLayout会对使用了layout_weight的子视图进行两次测量
测量和重新测量的代价非常昂贵,严重影响渲染速度,影响用户界面的流畅度

Hierarchy Viewer
是view层级可视化的工具,能帮助你发现冗余的view以及嵌套的布局

数据采集和分析工具
数据的采集工具Debug类或者DDMS工具
DDMS可采集正在运行的进程的函数调用信息
数据的分析使用TraceView
它主要通过每个函数的时间消耗找到性能瓶颈

使用Debug类
在代码开始的地方调用
startMethodTracing ()
在代码结束的地方调用
stopMethodTracing()
采集数据保存在/mnt/sdcard/下的一个文件

使用DDMS收集数据(适用于没有目标源码的情况)
选中要进行数据收集的应用
通过点击STOP左边的带红点的按钮可以开始和结束收集数据

使用TraceView分析数据
打开上面收集的文件找到耗时的方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值