Android开发的性能优化

来源:互联网 发布:淘宝卖的黄金是真的吗 编辑:程序博客网 时间:2024/06/10 01:04

Android性能优化主要内容包括布局优化、绘制优化、内存泄漏优化、响应速度优化、ListView/RecyclerView优化、Bitmap优化、线程优化以及代码性能优化,此处会一一讲解,并给出一些优化建议。

一、布局优化
优化思路很明确,就是尽可能的减少布局文件的中间层级,原因很简单,中间层级减少了,Android的View在measure、layout和draw上面耗费的时间就减少了,自然就快了。优化原则:

    1、尽可能的删除布局中无用的控件和层级,比如我们在做listView列表的时候,会用一个View放在item的底部做分割线,其实这个View是没必要的。可以通过其他手段实现。比如一个TextView的DrawableBottom属性设置一个图片等。    2、有选择的删除性能比较弱的ViewGroup,比如RelativeLayout。在既可以使用LinearLayout又可以用RelativeLayout,那就优先使用LinearLayout,因为后者的measure方法简单很多。    3、尽可能的减少布局中的嵌套层级,在用RelativeLayout可以减少布局的层及数量,使用LinearLayout会增加层级数量的情况下,还是考虑优先使用RelativeLayout。因为RelativeLayout虽然实现比较耗费资源,但是减少了层级,这时候二者有一个平衡,但是层级越少,代码越简洁,效率越高。    4、布局层级优化,太复杂的布局可以考虑使用<include>标签,简化布局代码。

二、绘制优化
绘制优化主要是指在View及ViewGroup的onDraw方法里面应避免执行太过复杂且大量的操作。体现在以下两方面:

    1、onDraw()里面不要创建新的布局变量尤其是对象,因为onDraw可能被高频率调用,这样就会产生大量的临时对象,增加内存消耗以及gc回收难度,耗费资源。    2、onDraw()里面不要做耗时操作以及量大的循环(如for循环一万次,while(true)循环),这样的循环被CPU反复调用将会很耗时间。视觉上UI就会有卡顿失帧。

三、内存泄漏优化
这个是项目开发中需要引起足够重视的问题,有效避免内存泄漏对开发者有较高的经验和开发意识要求。内存泄漏主要分两方面:一是开发者避免写出容易导致内存泄漏的代码,二是通过一些内存优化的三方库进行监督监视。此处主要分析一些内存泄漏优化的例子以增加理解。

场景1、静态变量导致的内存泄漏,这种泄露的主要原因是静态变量持有另一个对象,当该对象被回收的时候,由于静态变量依然持有,导致回收失败:

    public class AsyncTaskActivity extends AppCompatActivity {            static View sView;           @Override        protected void onCreate(Bundle savedInstanceState) {            super.onCreate(savedInstanceState);            setContentView(R.layout.activity_async_task);            sView = new View(this);        }    }

静态变量因为一直持有AsyncTaskActivity这个对象,所以导致回收该Activity对象失败。

场景2、单例模式下的内存泄漏,这种泄露很容易被我们忽略:单例内部持有Context或Activity对象,当Activity被释放时,依然被单例持有。

public class Test {    static Context mContext;    public static Test instance;    public static Test getInstance(Activity activity){        getObject(activity);        if (instance == null){            synchronized (Test.class){                if (instance == null){                    instance = new Test();                }            }        }        return instance;    }    static void getObject(Activity activity){        mContext = activity;        //TODO:    }}

场景3、属性动画引起的内存泄漏,属性动画中的无限循环动画在Activity中播放,如果在onDestroy方法中没有停止这个动画,那么由于Activity的view一直被持有,而该view又持有Activity,最终导致Activity无法被释放回收,引起内存泄漏。

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

响应速度优化的核心是避免在主线程中做耗时操作,若耗时操作无法避免,那就让其在子线程中执行。响应速度过慢更多的体现在Activity的启动速度和对用户交互时的响应速度。Android规定,如果Activity在5秒内无法响应屏幕触摸或者键盘输入时间,就会出现ANR; BroadcastReceiver如果10秒内还没执行完操作也会出现ANR。实际开发中ANR很难从代码上发现。解决方式是分析ANR日志,这个日志是ANR发生时被创建保存在/data/anr目录下的,另外,复杂的同步也可能导致ANR。

五、ListView/RecyclerView列表优化主要涉及以下几个方面:

1、ViewItem的复用。
2、不在Adapter的getView方法里面做耗时操作。比如直接加载图片,这时需要通过耗时操作来实现,比如Glide三方包。
3、控制异步任务的执行频率。比如在列表高速滑动的时候,getView依然加载图片或则数据,这时候瞬间就会产生数十个甚至更多的异步任务,大大加重CPU的负担,导致响应缓慢。解决方案是在列表滑动的时候停止加载数据,列表停下来后再加载数据。如下:

Public voidonScrollStateChanged(AbsLisrView view, int scrollState){    If(scrollState == OnScrollListener。SCROLL_STATE_IDLE){        isListSlid = true;        mAdapter.notifyDataSetChanged();    }else{          isListSlid = false          }}

然后再getView方法中:

If(isListSlid && mCangetBitmapFromNetWork){     imageView.setTag(uri);      imageLoader.bindBitmap(uri, imageView, imageWidth, imageHeight);}

经过上面两个步骤,能优化解决95%以上的列表加载卡顿。

六、Bitmap优化

    Bitmap的优化主要是通过设置和里的BitmapFactory.Options来对图片进行采样缩放图片,采样过程中有一个重要的参数:inSampleSize,    当他为1时,新的图片大小为原图大小;当他为2时,新的图片宽高均为原图的1/2,而大小为原图的1/4。也就是说inSampleSize是一个直接影响图片大小的倍率参数。inSampleSize小于1时,无效果。另外倍率参数inSampleSize的取值应为2的指数倍数关系,即inSampleSize = 2^x,其中x >= 0。    public class TestList {        public static Bitmap sampleBitmap(Resources res, int id, int rewWidth,int reqHei){        final BitmapFactory.Options options = new BitmapFactory.Options();        options.inJustDecodeBounds = true;        BitmapFactory.decodeResource(res, id, options);        options.inSampleSize = initSampleSize(options, rewWidth, reqHei);        options.inJustDecodeBounds = false;        return BitmapFactory.decodeResource(res, id, options);}    public static int initSampleSize(BitmapFactory.Options options, int rewWidth, int reqHei){        final int wid = options.outWidth;        final int hei = options.outHeight;        int sampleSize = 1;        if(wid > rewWidth || hei > reqHei){            final int newWid = wid / 2;            final int newHei = hei / 2;            while ((newWid / sampleSize ) >= rewWidth && (newHei / sampleSize ) > reqHei){                sampleSize *= 2;            }        }        return iSampleSize;    }}

上面decodesampleBitmap方法返回的对象就是经过优化的,在实际使用中就很简单了,比如我想让ImageView加载100*100的图片,就可以直接decodesampleBitmap(res, R.drawable.peacture, 100, 100);

七、线程优化:核心思路就是避免产生大量的子线程,并用线程池技术来实现多线程需求。

八、Java代码性能优化

    1、少用枚举类,枚举类将会占用远远超过整型数据的内存空间,可以用switch语句块替代。    2、开发细节的注意:针对字符串的拼接,使用StringBuffer替代String;慎用异常,使用异常会导致性能降低;数据额结构和数据算法的优化;及时IO等。这方便涉及到的细节很多,需要开发中事件中多注意,养成良好的开发习惯。

代码的微优化是非常耗费时间的,没有必要从头到尾将所有代码都优化一遍。开发者应该根据具体的业务逻辑去专门针对某部分代码做优化。比如应用中可能有一些方法会被反复调用,那么这部分代码就值得专门做优化。其它的代码,需要开发者在写代码过程中去注意。

原创粉丝点击