Android开发艺术探索——Android性能优化

这是我在学习过程中总结的知识
目的是希望日后回来看或者需要用的时候可以 一目了然 # 的回顾、巩固、查缺补漏
不追求详细相当于书本的精简版或者说是导读(想看详细的直接对应翻书),但会尽力保证读者都能快速理解和快速使用(随理解加深会总结的更加精简),但必要时会附上一些较详细解释的链接
脚注是空白的:表示还没弄懂的知识,了解后会添加

文章目录

    • @[TOC]
  • 15.1 Android的性能优化方法
    • 15.1.1 布局优化
    • 15.1.2 绘制优化
    • 15.1.3 内存泄露的优化
    • 15.1.4 响应速度优化和ANR日志分析
    • 15.1.5 ListView和Bitmap优化
    • 15.1.6 线程优化
    • 15.1.7 一些性能优化建议
  • 15.2 内存泄露分析之MAT工具
  • 15.3 提高程序的可维护性

本章介绍

  • 常见的性能优化方法
  • 提供程序的可维护性和可扩展性的思想

15.1 Android的性能优化方法

15.1.1 布局优化

核心思想——减少布局文件的层级

  • 删除布局中无用的空间和层级
  • 使用性能较低的ViewGroup,比如LinearLayout比RelativeLayout简单,耗能少
  • 采用include标签(布局重用)、merge标签(结合include,减少布局层级)和ViewStub(提供按需加载)

merge

两个竖直方向的LinearLayout,可以用merge去除被包含的LinearLayout

ViewStub

ViewStub继承了View
在网络异常时的界面,就没必要加载整个界面

15.1.2 绘制优化

是指View的onDraw方法要避免执行大量的操作

  1. onDraw中不要创建新的布局对象
  2. onDraw不要做耗时的任务,也不能是成千上万次的循环操作

15.1.3 内存泄露的优化

内存泄露的优化分为两个方面

  • 开发过程中避免写出有内存泄漏的代码
  • 通过分析工具比如MAT来找出潜在的内存泄露然后解决

1. 静态变量导致的内存
这些静态变量会导致Activity无法正常销毁

    private static Context sContext;
    private static View sView;

    private Button mButton;

    @SuppressLint("NewApi")
    @SuppressWarnings("deprecation")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        sContext = this;
		sView = new View(this);
		}

2. 单例模式导致的内存泄露
首先提供一个单例模式的类,可以接收外部的注册并将外部的监听器存储起来

package com.ryg.chapter_15.manager;

import java.util.ArrayList;
import java.util.List;

public class TestManager {

    private List<OnDataArrivedListener> mOnDataArrivedListeners = new ArrayList<OnDataArrivedListener>();

    private static class SingletonHolder {
        public static final TestManager INSTANCE = new TestManager();
    }

    private TestManager() {
    }

    public static TestManager getInstance() {
        return SingletonHolder.INSTANCE;
    }

    public synchronized void registerListener(OnDataArrivedListener listener) {
        if (!mOnDataArrivedListeners.contains(listener)) {
            mOnDataArrivedListeners.add(listener);
        }
    }

    public synchronized void unregisterListener(OnDataArrivedListener listener) {
        mOnDataArrivedListeners.remove(listener);
    }

    public interface OnDataArrivedListener {
        public void onDataArrived(Object data);
    }
}

现在让Activity实现OnDataArrivedListener接口并向TestManager注册监听,但是下面代码由于缺少解注册的操作所以会引起内存泄露
原因是Activity的对象被单例模式的TestManager所持有,而单例模式的特点是其生命周期和Application保持一致,因此Activity对象无法被及时释放

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        sContext = this;
		TestManager.getInstance().registerListener(this);

3. 属性动画导致的内存泄露
属性动画中有一类无限循环的动画,如果没有在onDestroy中去停止,那么动画会一直播放下去.这个时候Activity的View 被动画持有,而View又持有了Activity,最终Activity无法被释放
解决方法是调用animator.cancel()方法

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

Android规定,Activity如果5秒钟内无法响应屏幕触摸事件或者键盘输入事件就会出现ANR
BroadcastReceiver如果10秒钟之内还未执行完操作也会出现ANR
当一个进程发生了ANR以后,系统会在/data/anr目录下创建一个traces.txt文件,我们需要分析这个文件找出问题

15.1.5 ListView和Bitmap优化

ListView

  • 首先采用ViewHolder并避免在getView中执行耗时操作
  • 根据列表的滑动状态来控制任务的执行频率,比如快速滑动时不要开启大量的异步任务
  • 尝试开启硬件加速

Bitmap

  • 通过BitmapFactory.Options来根据图片采样缩放

15.1.6 线程优化

  • 使用线程池避免程序中存在大量的Thread
  • 线程池控制线程并发,放置出现阻塞现象

15.1.7 一些性能优化建议

  • 避免创建过多对象
  • 不要过多使用枚举
  • 常量使用static final 来修饰
  • 使用一些Android特有的数据结构,比如SparseArray和Pair等,性能更好
  • 适当使用软引用和弱引用
  • 采用内存缓存和磁盘缓存’
  • 尽量采用静态内部类,避免潜在的由于内部类导致的内存泄露

15.2 内存泄露分析之MAT工具

15.3 提高程序的可维护性

  • 私有成员以m开头
  • 静态成员以s开头

你可能感兴趣的:(Android理论类)