针对Android的性能优化集中哪些方面

发布网友

我来回答

2个回答

热心网友

一、概要:

本文主要以Android的渲染机制、UI优化、多线程的处理、缓存处理、电量优化以及代码规范等几方面来简述Android的性能优化

二、渲染机制的优化:

大多数用户感知到的卡顿等性能问题的最主要根源都是因为渲染性能。

Android系统每隔16ms发出VSYNC信号,触发对UI进行渲染, 如果每次渲染都成功,这样就能够达到流畅的画面所需要的60fps,为了能够实现60fps,这意味着程序的大多数操作都必须在16ms内完成。

如果你的某个操作花费时间是24ms,系统在得到VSYNC信号的时候就无法进行正常渲染,这样就发生了丢帧现象。那么用户在32ms内看到的会是同一帧画面。

Probably:也许是因为你的layout太过复杂,无法在16ms内完成渲染,有可能是因为你的UI上有层叠太多的绘制单元,还有可能是因为动画执行 的次数过多。这些都会导致CPU或者GPU负载过重。

Resolved:我们可以通过一些工具来定位问题,比如可以使用HierarchyViewer来查找Activity中的布局是否过于复杂,也可以使用手机设置里 面的开发者选项,打开Show GPU Overdraw等选项进行观察。

你还可以使用TraceView来观察CPU的执行情况,更加快捷的找到性能瓶颈。

浅谈Overdraw(过度绘制):

Overdraw(过度绘制)描述的是屏幕上的某个像素在同一帧的时间内被绘制了多次。在多层次的UI结构里面,如果不可见的UI也在做绘制的操作,这就会导致某些像素区域被绘制了多次。这就浪费大量的CPU以及GPU资源。 

Tips:我们可以通过手机设置里面的开发者选项,打开Show GPU Overdraw的选项,可以观察UI上的Overdraw情况

图解:蓝色,淡绿,淡红,深红代表了4种不同程度的Overdraw情况,我们的目标就是尽量减少红色Overdraw,看到更多的蓝色区域。

Tips:Overdraw有时候是因为你的UI布局存在大量重叠的部分,还有的时候是因为非必须的重叠背景。例如某个Activity有一个背景,然后里面 的Layout又有自己的背景,同时子View又分别有自己的背景。

仅仅是通过移除非必须的背景图片,这就能够减少大量的红色Overdraw区域,增加 蓝色区域的占比。这一措施能够显著提升程序性能。

注意:如需获取更多渲染机制的内容,请移步 https://www.oschina.net/news/60157/android-performance-patterns

三、UI方面的优化:

1)首先简单谈谈view的绘制流程:measure - layout - draw

ps:具体的流程网上一搜一大把+_+

2)子控件越多,绘制的时间也就越长。

对于Listview或者GridView这种多item的组件来说,复用item可以减少inflate次数,通过setTag,getTag的ViewHolder方式实现复用,这里要注意的是,holder中的控件最好reset后再赋值,避免图片,文字错乱。

*以下简单的例子:(尽量使用注解,有很多注解的开源框架可以使用:butterKnife, AndroidAnnotation, Dragger2)

static class ViewHolder{
    @InjectView(R.id.imageView1)
    ImageView imageView1;
    @InjectView (R.id.text1)
    TextView textView1;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder;
             
    if(convertView == null){
       holder = new ViewHolder();
       convertView = LayoutInflater.from(mContext).inflate(R.layout.listview_item, null);
       convertView.setTag(holder);
     }else{
         holder = (ViewHolder)convertView.getTag();
     }
             
         holder.imageView1.setImageResource(R.drawable.ic_launcher);
         holder.textView1.setText(mData.get(position));  
             
         return convertView;
}

3)UI ReView(视图的检查) 

1. 减少视图层级可以有效的减少内存消耗,因为视图是一个树形结构,每次刷新和渲染都会遍历一次。

2. 想要减少视图层级首先就需要知道视图层级,所以下面介绍一个SDK中自带的一个非常好用的工具hierarchyviewer。你可以在下面的地址找到它:your sdk path\sdk\tools

3. 如上图大家可以看到,hierarchyviewer可以非常清楚的看到当前视图的层级结构,并且可以查看视图的执行效率(视图上的小圆点,绿色表示流畅,*和红色次之),所以我们可以很方便的查看哪些view可能会影响我们的性能从而去进一步优化它。

hierarchyviewer还提供另外一种列表式的查看方式,可以查看详细的屏幕画面,具体到像素级别的问题都可以通过它发现。

4)一些标签的使用

<merge> :它在优化UI结构时起到很重要的作用。目的是通过删减多余或者额外的层级,从而优化整个Android Layout的结构,优化布局层数。

<include > :可以通过这个标签直接加载外部的xml到当前结构中,是复用UI资源的常用标签,来共享布局。

<ViewStub> : 动态加载view,此标签可以使UI在特殊情况下,直观效果类似于设置View的不可见性,但是其更大的意义在于被这个标签所包裹的Views在默认状态下不会占用任何内存空间。

四、多线程的处理:

1. Android 提供的多种多线程工具类 (AsyncTask, HandlerThread, IntentService, ThreadPool),许多操作都需要由 主线程(UI 线程)来执行,比如:

2. Android 系统的屏幕刷新频率为 60 fps, 也就是每隔 16 ms 刷新一次。如果在某次绘制过程中,我们的操作不能在 16 ms 内完成,那它则不能赶上这次的绘制公交车,只能等下一轮。

这种现象叫做 “掉帧”,用户看到的就是界面绘制不连续、卡顿。

3. HandlerThread 就是MessageQueue,Looper和 Handler 的组合。每个应用启动时,系统会创建一个该应用的进程以及主线程,这里的主线程就是一个 HandlerThread。

4. 注意问题:

1)多线程并发访问资源要遵循重要的原则就是 原子性、可见性、有序性。没有同步机制的情况下,多个线程同时读写内存可能会导致意料之外的问题:

①线程安全的问题; ② UI 组件的生命周期并不确定;③线程引用导致的内存泄漏问题

2)不要在任何子线程持有 UI 组件或者 Activity 的引用

3)保持响应不发生ANR: 

①从UI线程中移除费时操作这个方式还可以防止用户操作出现系统不响应(ANR)对话框。需要做的就是继承AsyncTask来创建一个后台工作线程,并实现doInBackground()方法。

②还有一种方式就是自己创建一个Thread类或者HandlerThread类,明确设定线程的优先级。

4)使用StrictMode来检查UI线程中可能潜在的费时操作,使用一些特殊的工具如Safe.ijiami、Systrace或者Traceview来寻找在你的应用中的瓶颈;用进度条向用户展示操作进度。

五、缓存处理:

简单的说说缓存优化的几个方面:

缓存机制:网络+数据库。为了避免从网络获取重复的数据,可以在activity或者fragment或者每个组件设置一个最大请求间隔。

比如一个listview,第一次请求数据时,保存一份到数据库,并记下时间戳,当下次重新初始化时,判断是否超过最大时间间隔(如5分钟),如果没有,只加载数据库数据,不需要再做网络请求。

(当然,还有一些隐式的http请求框架会缓存服务器数据,在一定时间内不再请求网络,或者当服务器返回304时将之前缓存的数据直接返回)

网络方面:1)需要服务端配合的:json数据格式,WebP代替jpg,支持断点续传,多个请求合并成一个,尽量不做重定向,服务器缓存以及负载均衡等。

2)对客户端本身,除了上述的实现,我们还需要合理的缓存,控制最大请求并发量,及时取消已失效的请求,过滤重复请求,timeout时间设置,请求优先级设置等。

* WebP:WebP 的优势体现在它具有更优的图像数据压缩算法,能带来更小的图片体积,而且拥有肉眼识别无差异的图像质量;

同时具备了无损和有损的压缩模式、Alpha 透明以及动画的特性,在 JPEG 和 PNG 上的转化效果都相当优秀、稳定和统一。

转换后的 WebP 支持 Alpha 透明和 24-bit 颜色数,不存在 PNG8 色彩不够丰富和在浏览器中可能会出现毛边的问题。

* 更多了解请看:http://isux.tencent.com/introction-of-webp.html

六、电量优化:

有下面一些措施能够显著减少电量的消耗:

引用:Android性能优化的浅谈

热心网友

性能优化的好坏,可以决定了一个app的寿命长短,优化性能已成为重中之重:
1 app启动优化:
为了缩短app的启动时间,在application里面的onCreate()不要做耗时操作,在默认启动的第一个activity的onCreate(),onResume()生命周期方法里面不要做耗时操作。如果非要做,会出现黑屏现象,建议在第一个启动的acitivity的theme加个背景,背景图可以是闪屏页的图片。
2 app布局优化:
多使用include,merge, viewStub,竟可能的减少布局嵌套层数。
3 内存优化:
要做好内存优化,首先要避免内存泄露(这是一大块,我就举一些简单的:容易引起内存泄露的原因是未使用的对象还保持着activity的引用,比如handler,AsyncTask等,还有一些注册后要进行反注册,比如非常驻型广播,eventBus之类的,关于一些数据库操作,cursor记得要close,bitmap操作,记得要进行recycle()),如果之前已经出现,可以使用leakcanary 进行检测,从而消除隐患。
4 响应优化:
为了防止ANR的异常出现,在UI线程,不要做耗时操作,对于一些耗时操作,应该放到workThread线程中去处理,然后通过handler或者其他方式来更新ui。

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com