Android性能优化方法总结

概述

由于Android设备内存有限,特别是一些配置比较低的手机在运行较大的java程序时有时候由于内存不够用的,会出现OOM和ANR等情况,严重影响用户的使用。那么怎样做会降低上述情况的发生呢?本文总结了一些比较好的android性能优化方式,希望能给学习android开发的朋友们带来帮助。
目前,关于Android性能优化的方案主要有以下方式:

  • 布局优化;
  • 绘制优化;
  • 内存泄露优化;
  • 响应速度优化;
  • 线程优化

布局优化

android程序编译时,层级越多越复杂绘制的工作量也就越高,性能当然也就越不好。所以,在程序开发中布局文件的绘制在满足要求的情况下应该越简单越好,层级越少越好。
首先,我们应该多使用性能较高的FrameLayout、LinearLayout等性能较高的ViewGroup类作为父布局,像RelativeLayout这样的比较复杂、性能较低的ViewGroup类有选择地进行使用。
而且,特别重要的是在绘制布局文件后多检查,将一些无用的控件和层级删去。
布局优化中还有一些特别重要的小窍门,即使用<include>、<merge>、<ViewStub> 等常用的布局文件标签。这些标签想必大家都不止一次运用,不再过多说明。注意一点就是一般情况下<merge>标签和<include>标签一般是联合使用的,用来减少所包裹布局的层级。


绘制优化

所谓绘制优化,就是程序开发中尽量不要过多过强地干扰android中各类View、ViewGroup的绘制。简言之,就是不要在onDraw()方法中做一些比较耗时的操作。比如数据的交互、布局的刷新等。因为Google给出的建议是View的绘制过程最好不要超过16ms,否则的话就会使得程序运行时显得比较卡,影响用户的使用。


内存泄露优化

android程序中,如果一个对象不需要再使用但仍然被其他对象持有引用,就有可能造成该对象无法被系统回收,以致该对象在堆中所占用的内存单元无法被释放而造成内存空间浪费,这中情况就是内存泄露。内存泄露有很多种,常见的举例如下:

单例导致内存泄露

单例模式在Android开发中会经常用到,但是如果使用不当就会导致内存泄露。因为单例的静态特性使得它的生命周期同应用的生命周期一样长,如果一个对象已经没有用处了,但是单例还持有它的引用,那么在整个应用程序的生命周期它都不能正常被回收,从而导致内存泄露。

public class MainActivity {
    private static MainActivity mMainActivity;
    private Context mContext;

    private MainActivity(Context context) {
        this.mContext = context;
    }

    public static MainActivity getInstance(Context context) {
        if (mMainActivity == null) {
            mMainActivity = new MainActivity(context);
        }
        return mMainActivity;
    }
}

上面代码中,当启动一个Activity,并调用getInstance(Context context)方法去获取MainActivity的单例,传入Activity.this作为context,这样MainActivity类的单例sInstance就持有了Activity的引用,当我们退出Activity时,该Activity就没有用了,但是因为sIntance作为静态单例(在应用程序的整个生命周期中存在)会继续持有这个Activity的引用,导致这个Activity对象无法被回收释放,这就造成了内存泄露。

为了避免这样单例导致内存泄露,我们可以将context参数改为全局的上下文:

private MainActivity(Context context) {
this.mContext = context.getApplicationContext();
}
全局的上下文Application Context就是应用程序的上下文,和单例的生命周期一样长,这样就避免了内存泄漏。

单例模式对应应用程序的生命周期,所以我们在构造单例的时候尽量避免使用Activity的上下文,而是使用Application的上下文。

静态变量导致内存泄露

静态变量存储在方法区,它的生命周期从类加载开始,到整个进程结束。一旦静态变量初始化后,它所持有的引用只有等到进程结束才会释放。比如下面这样的情况,在Activity中为了避免重复的创建Bean,将mBean作为静态变量:

public class MainActivity extends Activity {

    private static Bean mBean;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (mBean != null) {
            mBean = new Bean(this);
        }
    }
}
class Bean {
    public Bean(Activity activity) {
    }
}

Bean作为Activity的静态成员,并且持有Activity的引用,但是mBean作为静态变量,生命周期肯定比Activity长。所以当Activity退出后,mBean仍然引用了Activity,Activity不能被回收,这就导致了内存泄露。
静态持有很多时候都有可能因为其使用的生命周期不一致而导致内存泄露,所以我们在新建静态持有的变量的时候需要多考虑一下各个成员之间的引用关系,并且尽量少地使用静态持有的变量,以避免发生内存泄露。同时也可以在适当的时候讲静态量重置为null,使其不再持有引用,这样也可以避免内存泄露。


响应速度优化

android程序尽量不要在主线程上做一些特别耗时的操作,这样极易引发ANR(Application no response)。主线程的耗时操作不要超过5s,广播接收器中的操作不要超过10s,上述两种情况都势必会引起ANR。所以我们尽量适时的开启子线程,让耗时操作在子线程完成。


线程优化

线程优化主要是指在程序中不要随便就新建子线程,因为子线程不是用完只有就会被立马回收的。在回收之前会一直占用着手机内存,影响APP的运行效率。所以呢,还是能重复利用的就重复利用。比如运用线程池的思想,当我们需要开启子线程的时候就去线程池里面捞一个闲置的线程出来。这样既节约了线程新建的时间和内存,也避免了开启不必要的线程资源,一举两得。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值