其它Android知识Android开发

Android 性能优化(一)

2017-02-23  本文已影响109人  王世军Steven

Android作为一种移动设备,内存和CPU资源都是受限的. 过多地使用内存会导致内存溢出(OOM),过多的使用CPU会导致手机卡顿,甚至出现程序无法响应的情况(ANR). 本文介绍一系列优化方法.

1. 布局优化

1.1 尽量减少布局的层级.

布局的层级少了,那么Android绘制时的工作量就少了,自然能后提高性能.

1.2 ViewGroup的选择.

有选择的使用性能较低的ViewGroup如RelativeLayout的功能比较复杂绘制过程消耗更多的CPU资源 , 尽量使用性能较高的ViewGroup如LinearLayout 和FrameLayout.

1.3 <include> 标签

<include> 标签可以将指定的布局加载到当前布局 .

定义一个布局文件,layout_include.xml文件.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:background="#f00"
              android:layout_width="match_parent"
              android:layout_height="match_parent">
    <Button
        android:layout_width="wrap_content"
        android:text="测试按钮"
        android:textSize="30sp"
        android:layout_height="wrap_content"/>
</LinearLayout>

使用 <include>标签引用布局.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:id="@+id/activity_main"
    android:background="#0f0"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <!-- 使用 include 标签 -->
    <include
        android:layout_height="200dp"
        android:layout_width="200dp"
        layout="@layout/layout_include"/>
</LinearLayout>

效果图如下:

效果图

1.4 <merge> 标签

<merge> 标签主要和 <include> 标签一起使用,比如在上面的样例中当前布局使用了一个竖直方向的LinearLayout,在被引用的布局中也使用了一个竖直方向的LinearLayout此时内层的LinearLayout就显得多余了.可以使用<merge>标签替代.从而达到减少布局层级的目的.

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
    <Button
        android:layout_width="wrap_content"
        android:text="测试按钮"
        android:textSize="30sp"
        android:layout_height="wrap_content"/>
</merge>

1.5 ViewStub

ViewStub继承自View并且宽高都是 0,它本身不参与任何布局和绘制过程. 他可以按需添加布局,有些布局一开始是不需要的,因此可以先不加载,在需要时再进行布局加载.

加载ViewStub前界面
加载ViewStub后界面

创建layout_viewstub.xml文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:id="@+id/stub_import"
              xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">
    <TextView
        android:background="#00f"
        android:layout_width="match_parent"
        android:text="View_Stub测试界面"
        android:textSize="30sp"
        android:layout_height="match_parent"/>
</LinearLayout>

activity_main.xml 中添加ViewStub节点

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:id="@+id/activity_main"
    android:background="#0f0"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- 使用 include 标签 -->
    <include
        android:layout_height="200dp"
        android:layout_width="200dp"
        layout="@layout/layout_include"/>
    <!-- 使用ViewStub -->
    <ViewStub
        android:layout_width="200dp"
        android:id="@+id/panel_import"
        android:layout="@layout/layout_viewstub"
        android:inflatedId="@+id/stub_import"
        android:layout_height="200dp"/>
    <Button
        android:layout_width="wrap_content"
        android:onClick="onclick"
        android:text="加载布局"
        android:layout_height="wrap_content"/>
</LinearLayout>

修改MainActivity.java

public void onclick(View view) {
    // 加载ViewStub方式一
    // ((ViewStub)findViewById(R.id.panel_import)).setVisibility(View.VISIBLE);
    // 加载ViewStub方式二  
    ((ViewStub)findViewById(R.id.panel_import)).inflate();
}

android:id="@+id/panel_import" : 设置ViewStub的id.
android:id="@+id/panel_import" : ViewStub加载的布局的根布局的id.
android:layout="@layout/layout_viewstub" : 设置加载布局的资源id.
注意 : ViewStub不支持<merge>标签

2. 绘制优化

绘制优化主要是指View的onDraw方法要避免大量操作. 主要体现如下两方面 :

3. 内存泄露优化

内存泄露的优化分为两部分.

3.1 静态变量导致内存泄露

public class MainActivity extends AppCompatActivity {
    private static Context sContext;
    private static View sView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 设置
        sContext = this;
        sView = new View(this);
    }
}

上面的代码容易造成内存泄露.

3.2 单例模式导致的内存泄露

单例模式造成内存泄露主要是单例对象保存的外部变量的引用没有被移除造成的.比如单例对象有添加监听者的方法但是没有移除监听者对象的方法.

3.3 属性动画导致的内存泄露

Android 3.0 增加了属性动画,这种动画需要在onDestory中取消动画animator.cancel()否则动画就会无限循环地执行,造成动画对象会持有View,View持有Activity,最终造成Activity无法释放.造成内存泄露.

属性动画持有关系

3.4 响应速度优化和ANR日志分析

Android系统规定:

当系统发生ANR时会在 data/anr目录下生成traces.txt文件.通过分析这个文件就可以找到ANR的原因.

我们在onCreate方法中添加如下代码模模拟ANR

while(true);

查看traces.txt部分内容如下:

traces.txt 文件部分内容

便可以定位出问题所在了.

4. ListView 和 Bitmap优化.

4.1 ListView 优化主要有三个方面

4.2 Bitmap优化

Bitmap优化主要是通过加载压缩后的图片来进行优化的.

5. 线程优化

尽量使用线程池代替开启新的线程.

6. 性能优化建议

参考 : <Android开发艺术探索>

上一篇 下一篇

猜你喜欢

热点阅读