Android性能优化

为什么要性能优化?

因为手机CPU和内存受到限制,过多使用内存会可能会导致内存溢出、过度使用CPU可能会导致手机卡顿,从而出现了我们的性能优化。

主要从俩个方面进行优化 1.布局优化、2.内存优化。

先大概给大家普及一下。

布局优化:

能复用的就复用。布局较简单的则使用LinearLayout(性能耗费低)。从而避免不需要给Id的控件也给Id占用空间。

布局复杂的则使用RelativeLayout(耗费性能高)。虽然他会在R文件生成很多无用的Id但是他没有层级嵌套。当咱们LinearLayout布局层级嵌套超过四层时我们就要考虑使用RelativeLayout。

因为布局优化的原理是布局层级少 ->> 绘制的工作量少 ->> 绘制速度快 ->> 性能提高。:

内存优化的话分为:内存泄漏的优化,Bitamp的优化,ListView,线程。

内存泄漏只要有:单例模式(咱们通常引用activity的上下文,单例模式的类是静态类,activity销毁时单利类还保持这activity的引用造成GC无法回收。解决方法就是咱们写个全局的App,在onpush()方法执行时赋值为null(这里也包括咱们的静态变量同时也赋值为null)。Bitmap对图片的一个压缩的优化,主要就是通过Options计算出二次采样率然后设置inSampleSize属性按几倍进行压缩,从而得到图片的一个优化。对Bitmap"对象"的优化使用inBitmap的主要作用是复用之前bitmap在内存中申请的内存,其实这是对象池的原理,以解决对象频繁创建再回收的效率问题。(inBitmap只能在3.0以后使用。))还有就是线程,主要就是使用线程池对线程的一个复用,避免重复创建对象和GC的频繁的回收。

一些有效的优化方法

布局优化

使用<include>、<merge>和<ViewStub>标签

主要思想:布局中的层级少了,这就意味着Android的绘制工作少了,那么程序的性能自然就提高了。

要提取布局间的公共部分,通过提高布局的复用性从而减少测量 & 绘制时间

尽可能少用布局属性 wrap_content

布局属性 wrap_content 会增加布局测量时计算成本,应尽可能少用

1 选择 耗费性能较少的布局

性能耗费低的布局 = 功能简单 = FrameLayout、LinearLayout

性能耗费高的布局 = 功能复杂 = RelativeLayout(每一个控件都有一个Id,都会在R文件里创建对象,在UI界面复杂的时候可以用。)

注:

嵌套所耗费的性能 > 单个布局本身耗费的性能

即 完成需求时:宁选择 1个耗费性能高的布局,也不采用嵌套多个耗费性能低的布局

减少布局的层级(嵌套)

原理:布局层级少 ->> 绘制的工作量少 ->> 绘制速度快 ->> 性能提高

关于标签我在这里主要就是对<include>标签进行介绍。

1.使用<include>标签(布局复用需用到的标签)

a是我随便写的一个布局我进行了引用。这里可能有的小伙伴要有疑问了。这个由于是复用布局我们不用指定ID,当我们findViewById的时候,会自动找到布局a里面定义的控件ID。使用<include>标签会减少布局的绘制。

2.<merge>标签(整体为merge)

<merge>标签主要要和<include>标签搭配使用,当<include>标签的最外层布局和所处的当前布局一样时,比如说都是垂直方向的LinearLayout,此时便可以将<include>标签的最外层布局的LinearLayout改成<merge>标签

3.<ViewStub>标签:

<ViewStub>标签主要是一个轻量级的按需加载的布局控件,特点是像<include>标签一样包含一个布局文件,还有一个是可以在必要的时候显示和消失,所以ViewStub控件有利于显示一些网络加载或者异常时的界面。


二丶内存优化

绘制优化

绘制优化是指View的onDraw方法要避免大量的操作,主要体现在内存和CPU两个方面:

onDraw中不要创建新的局部对象

因为onDraw可能会被频繁的调用而导致大量的对象被创建,这会导致占用过多的内存从而频繁地gc;(GC垃圾回收,执行GC时所有的线程操作都会暂停,等待GC的操作完成,大量不停的GC操作会占用帧间隔时间的16ms,在这16ms时间里做了长时间的GC操作,从而使其他操作时间变短)

onDraw中不要进行耗时的操作

频繁的耗时操作会占用CPU的时间大量的时间,导致程序卡顿。

1.3 内存泄漏优化

内存泄漏:程序在销毁时,还有一些引用没有被释放(或者说GC没有回收),导致这些对象占用的内存无法被使用(无用的对象占据着内存空间,使得实际可使用内存变小,形象地说法就是内存泄漏了。)

影响

应用卡顿:泄漏的内存影响了GC的内存分配,过多的内存泄漏会影响应用的执行率

GC回收的原则:被全局变量(static)、栈变量和寄存器等直接引用和间接引用的对象不能被回收。

常见的内存泄漏:

1:静态变量导致的内存泄漏(静态变量伴随着整个App的存亡。)

这个静态变量mContext引用这这个Activity,


2.单利模式,泄漏的原因是OrmHelper会一直持有context对象


解决方法就是将我们传入的Context赋值成全局的getApplicationContext()

3.属性动画导致内存泄漏 (在android3.0 Google 提供了属性动画)。

动画播放完之后, 尽管我们看不到动画的播放效果,但在内部处于无限循环播放的状态

解决办法:解决方法就是在onDestory或动画结束监听中调用animator.cancle()


在内部处于无限循环播放的状态

4.集合对象没有清理造成内存泄漏。

我们通常把一些对象的引用加入到了集合中,当我们不需要该对象时,如果没有把它的引用从集合中清理掉,这样这个集合就会越来越大。

5.资源对象没有手动关闭或处理。

资源性对象(BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap)

6.强引用数据。

new 出对象的时候,对象被引用的时候称之为强引用,当不在引用的时候就不再叫强引用,GC可以对其进行一个回收。

总结

开发中尽量避免写出有内存泄漏的代码,但并不是每个内存泄漏都需要解决,我们只是尽量的让内存泄漏减少,来优化app内存。

这里交给大家怎么去检测你的代码是否有内存泄漏

LeakCanary。

1.   导入依赖:

debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5'

releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'

如果以上三个依赖不行,试一下下面的俩个依赖

debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1'  

releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1' 

创一个类继承Appliaction 初始化安装检测器。

LeakCanary.install(this)(这一行代码就是当我们运行App时进行安装检测工具的代码。如果应用要上线的话,只需把这行代码注释就可以)


记得在AndroidManifest里的<application>里配置即下面的的代码

    android:name=".AppApplication">

运行App会自动安装检测软件(Leaks)

特别要注意:在我自己检测时:只有我偶次数运行App时才会检测出内存的泄漏。也就是第一次运行不检测,退出App再进入App才会检测。检测需要花一小段时间,耐心等待。。如果有内存泄漏会推送到你手机上。


这里主要就看倒数一行、二行。你们仔细看一下倒数一行,二行,就会知道到底是哪里内存泄漏了。

ViewHolder的优化  :

采用ViewHolder进行缓存并且避免在getView中执行耗时操作。这里就不给大家介绍ViewHolder的原理了,相信大家都明白。

Bitmap优化(图片压缩,内存占用计算=宽×高×色彩空间)

Bitmap优化主要是通过BitmapFactory的Options对象进行的方法:

利用Options先计算出采样率inSampleSize并返回给Options,最后通过改变的Options对图片进行压缩 

在解析Bitmap时,有个可选的Options对象,其中inSampleSize参数可以影响缩放比的结果。当使用该参数值时要求大于1且是2的倍数,比如在inSampleSize=2时,缩放比被缩小2倍(该功能只有缩小没有放大的可能),即“缩放比=原始缩放比×(1/2)”。对内存结果的影响是缩小4倍,因为宽/高都被缩小2倍。该值默认不生效,需要手动设置。


当options.inJustDecodeBounds 的值是true,只是读取图片的边,而不是读取整个图片,所以Bitmap bitmap = BitmapFactory.decodeFile(imagePath,options);得到的bitmap是空的。

线程优化

线程优化主要体现在避免大量的创建和销毁线程,因此线程优化的思想就是使用线程池。使用线程池的好处就是,可以重用线程避免创建和销毁大量线程,还可以控制并发数以避免阻塞。线程池的基本作用就是进行线程的复用。(线程的创建和销毁都需要时间,当有大量的线程创建和销毁时,那么这些时间的消耗则比较明显,将导致性能上的缺失

2、大量的线程创建、执行和销毁是非常耗cpu和内存的,这样将直接影响系统的吞吐量,导致性能急剧下降,如果内存资源占用的比较多,还很可能造成OOM

3、大量的线程的创建和销毁很容易导致GC频繁的执行,从而发生内存抖动现象,而发生了内存抖动,对于移动端来说,最大的影响就是造成界面卡顿)

使用线程池管理线程的优点

1、线程的创建和销毁由线程池维护,一个线程在完成任务后并不会立即销毁,而是由后续的任务复用这个线程,从而减少线程的创建和销毁,节约系统的开销

2、线程池旨在线程的复用,这就可以节约我们用以往的方式创建线程和销毁所消耗的时间,减少线程频繁调度的开销,从而节约系统资源,提高系统吞吐量

3、在执行大量异步任务时提高了性能

4、Java内置的一套ExecutorService线程池相关的api,可以更方便的控制线程的最大并发数、线程的定时任务、单线程的顺序执行等

关于优化的还有很多:

用户电量的优化、用户流量的优化、启动速度的优化、消除App卡顿......等等。这里不给大家一一介绍了

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,651评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,468评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,931评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,218评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,234评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,198评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,084评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,926评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,341评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,563评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,731评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,430评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,036评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,676评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,829评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,743评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,629评论 2 354

推荐阅读更多精彩内容