读书笔记(15) Android性能优化
来源:互联网 发布:异构系统数据集成 编辑:程序博客网 时间:2024/06/05 08:19
这些读书笔记是根据《Android开发艺术探索》和《Android群英传》这两本书,然后将书上的一些知识点做一下记录。方便学习和理解,如果有存在侵犯版权的地方,还麻烦告知。个人强烈建议购买这两本书。真心不错。
本节是和《Android开发艺术探索》中的第15章 “Android性能优化” 有关系,建议先买书查看这一章。
[]Android 性能优化
2015年Google在YouTube上发布了关于Android性能优化典范的专题视频。
https://www.youtube.com/playlist?list=PLWz5rJ2EKKc9CBxr3BVjPTPoDPLdPIFCE
过多地使用内存会导致程序内存溢出,即OOM。而过多的使用CPU资源,一般是指做大量的耗时任务,会导致手机变得卡顿甚至出现程序无法响应的情况,即ANR。
内存泄漏并不会导致程序功能异常,但是它会导致程序的内存占用过大,这将提高内存溢出的发生几率。
()布局优化
布局优化其实就是尽量减少布局文件的层级,因为布局中的层级少了,程序绘制时的工作量少啦,那么布局性能就有提高。
{}删除布局中无用的控件和层级,有选择性的使用性能较低的ViewGroup。
如果布局中既可以使用LinearLayout也可以使用RelativeLayout,那么就采用LinearLayout,因为RelativeLayout的功能比较复杂,它的布局过程需要发费更多的CPU时间。
如果通过一个LinearLayout无法实现,需要嵌套的方式来实现。通过RelativeLayout也能实现,那么就采用RelativeLayout,因为嵌套的LinearLayout就增加了布局的层级。
{}采用< include>标签< merge>标签和ViewStub控件。
include标签主要用于布局重用。
include标签只支持以android:layout_*开头的(可以通过代码提示查看)和android:id这些属性,其他属性不支持,
如果include标签指定了id属性,同时include标签的布局文件的根元素也指定了id属性,那么以include标签指定的id属性为准。
如果include标签指定了android:layout_*属性,那么必须指定 android:layout_height和android:layout_width,否则其他android:layout_*属性无效,并且不能通过编译。
merge标签一般和include标签配合使用,主要用于降低减少布局的层级。
如果include标签中的布局是竖直的LinearLayout,引用include标签的布局文件也是竖直的LinearLayout,那么include标签中的竖直的LinearLayout可以用merge标签代替。
ViewStub控件主要用于按需加载的功能,当需要时才会将ViewStub中的布局加载到内存中显示。比如网络连接失败时,加载一个网络异常界面。
ViewStub继承View,它非常轻量级且宽和高都是0,因此ViewStub不参与任何的布局和绘制过程。
ViewStub可以通过setVisibility(View.VISIBLE)或者inflate()加载后,ViewStub就不存在了,被它内部的布局替换掉。
<ViewStub android:id="@+id/***" android:layout="@layout/***" android:layout_width="match_parent" android:layout_height="match_parent" />
()绘制优化
绘制优化是指View的onDraw方法中要避免执行大量的操作。
{}onDraw方法中不要创建新的局部对象,因为onDraw方法可能会被频繁调用,这样就会在一瞬间产生大量的临时对象,这不仅占用了过多的内存而且还会导致系统更加频繁gc。
{}onDraw方法中不要做耗时的任务,也不能执行大量的循环操作。尽管每次循环都很轻量级,但是大量的循环仍然十分抢占CPU资源,这会导致View的绘制过程不流畅。
()内存泄漏优化
内存泄露,就是该被释放的内存没有被释放,一直被某个或某些实例所引用但不能被使用,导致GC不能回收。可以理解为长生命周期的对象一直持有短生命周期对象的引用,导致短生命周期对象一直被引用而无法被GC回收。内存泄漏是造成OOM的主要原因之一。
{}静态变量导致的内存泄漏
在Activity中一个静态变量持有当前Activity对象,会导致Activity无法释放。
下列代码会出现内存泄漏
public class TextActivity extends Activity { private static View view; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); view=new View(this); }}
{}非静态内部类导致的内存泄漏
非静态的内部类和匿名内部类都会隐式地持有其外部类的引用。静态的内部类不会持有外部类的引用。
下列代码会出现内存泄漏
()非静态的内部类public class TextActivity extends Activity { private static MyInside myInside; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); myInside = new MyInside(); } public class MyInside { }}()非静态匿名内部类public class TexActivity extends Activity { private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.text); Message message = Message.obtain(); mHandler.sendMessage(message); }}
mHandler作为一个非静态匿名内部类,会持有外部类(TexActivity)的引用,对于消息机制是Looper不断的轮询从消息队列取出未处理的消息交给Handler处理,而每一个消息又持有一个mHandler的引用,每一个mHandler又持有TexActivity的引用,所以如果在Activity退出后,消息队列中还存在未处理完的消息,导致该Activity一直被引用,其内存资源无法被回收,导致了内存泄漏。
解决方案:将内部类定义为静态内部类或将内部类抽取出来封装成一个单例。
{}单例模式导致的内存泄漏
因为单例模式有其静态的特点,其生命周期和应用一样长,如果单例对象中包含了一个其他对象的引用,那么即使这个对象不再使用,依然存在一个单例对象引用它,造成无法回收。
下列代码会出现内存泄漏
public class DataListener { private static DataListener mDataListener; private Context mContext; private DataListener(Context mContext) { this.mContext = mContext; } public static DataListener getDataListener(Context mContext) { if (mDataListener == null) { mDataListener = new DataListener(mContext); } return mDataListener; }}public class TextActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.text); DataListener.getDataListener(this); }}
解决方案:将Context对象用Application对象来替代。
{}资源未回收导致内存泄漏
()属性动画导致的内存泄漏
属性动画中有一类无限循环的动画,如果在Activity中播放此类动画且没有在onDestroy中去停止动画,那么动画会一直播放下去。因为Activity中的View会被动画持有,而View又持有Activity,最终Activity无法释放。解决的方法是在onDestroy中调用cancel()来停止动画。
()BraodcastReceiver、Cursor、File、FileStream、Bitmap等资源的使用,应该在Activity销毁时及时关闭或者注销,否则这些资源将不会被回收,造成内存泄漏。
()响应速度优化和ANR日志分析
响应速度优化主要是避免在主线程中做耗时操作,但是有时候的确要执行耗时操作,可以将耗时操作放在子线程中执行,即采用异步的方式执行耗时操作。
Android中规定,Activity如果5秒钟之内无法响应屏幕触摸事件或者键盘输入事件就会出现ANR,BroadcastReceiver如果10秒钟之内还未执行完操作就会出现ANR。
如果一个进程出现ANR,系统会在data/anr目录下创建一个文件traces.tex和一系列traces_***.tex,分析这个文件就能定位出ANR的原因。
()ListView和Bitmap优化
ListView优化在12章中已经做了详细的介绍,主要是采用ViewHolder,并避免在getView中执行耗时操作,其次是根据列表的滑动状态来控制任务的执行频率。最后可以尝试开启硬件加速来使ListView的滑动更加流畅。
Bitmap优化在12章中已经做了详细的介绍,主要是通BitmapFactory.Options来对图片进行二次采样。
()线程优化
线程优化主要是采用线程池,因为线程池可以重用内部线程,从而避免了线程的创建和销毁使带来的性能开销,同时线程池还能有效地控制线程的最大并发数,避免大量的线程因互相抢占系统资源从而导致阻塞现象发生。
()一些性能优化建议
{}避免创建过多的对象
{}不要过多的使用枚举,枚举占用的内存空间要比整型大
{}常量使用 static final 修饰
{}采用一些Android特有的数据结构,比如SparseArray和Pair等,因为它们具有更好的性能。
{}适当的使用软应用和弱引用
{}采用内存缓存和磁盘缓存
{}尽量采用静态内部类,这样可以避免潜在的由于内部类而导致的内存泄漏
[]内存泄漏分析工具
()MAT
()LeakCanary
{}导LeakCanary的jar包
dependencies {..........debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1'releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1'}
{}LeakCanary引用
public class ExampleApplication extends Application { private RefWatcher mRefWatcher; @Override public void onCreate() { super.onCreate(); mRefWatcher = LeakCanary.install(this); }}
注:
LeakCanary会单独安装一个app,如果出现内存溢出会发出通知。点击通知就能了解内存溢出的详情。
LeakCanary默认监听Activity内存溢出,如果需要监听其他的类需要调用mRefWatcher.watch()方法。
- 读书笔记(15) Android性能优化
- 《Android开发艺术探索》读书笔记 (15) Android性能优化
- 《Android群英传》读书笔记10.Android性能优化
- 《Android应用性能优化》之读书笔记
- java 性能优化读书笔记
- 前端性能优化---读书笔记
- 《Java性能优化...》读书笔记
- 读书笔记-Android开发艺术探索-第15章-Android性能优化
- 《Android群英传》读书笔记(11)第十章:Android性能优化
- Android群英传读书笔记第10章(Android性能优化)
- 我的Android读书笔记——(4)Android性能优化
- C++应用程序性能优化读书笔记
- c程序性能优化读书笔记
- 【Android】android性能优化
- 【Android】Android性能优化
- 【Android】Android性能优化
- 【Android】【性能优化】 Android 性能优化
- 读书笔记(备忘)-.NET性能优化
- SSH框架整合
- linux应用层定时器 sleep usleep
- leetcode(4),Move Zeroes详解(python)
- MongoDB 导入Json数据( 需要用户名密码 )
- 键盘view 上移
- 读书笔记(15) Android性能优化
- 使用Docker容器模拟分布式flume
- 辞职的正确打开方式:教你如何摆脱被奴役的现状!
- JVM 常用分析工具(一)----jstat
- 直接插入排序思考与代码实现
- 刀塔传奇-王信文 分享总结
- 【腾讯Bugly干货】老司机教你“飙”EventBus3
- 正则表达式基本语法
- 为CentOS安装防DDOS攻击软件DDoS-Deflate