15.1.1布局优化
1.布局优化的思想:减少布局文件的层级(层级少了,绘制时的工作量就少了)
方法一:减少布局文件的层级
优化步骤: 1.1.删除布局中无用的控件和层级 1.2.选择简单高效的viewGroup 排行榜:FramLayout/LinearLayout>RealativeLayout(原因:RealativeLayout功能复杂,布局过程需要更多的cpu时间) 1.3.但有的时候FramLayout和LinearLayout想要完成产品需求需要嵌套很多次,这个时候就推荐使用一个RealativeLayout搞定 (也就是说布局简单的时候使用FramLayout/LinearLayout,复杂的时候需要嵌套多个FramLayout/LinearLayout的时候使用RealativeLayout)
方法二:标签优化采用
<include> :布局重用 <include layout="@layout/abc.xml"> <merge> :一般和<include>配合使用,减少布局的层级 <ViewStub>:按需加载(就是加了<ViewStub>标签后,系统会在需要<ViewStub>下的布局的时候,才加载到内存)标签优化注意事项:
<include> :<include> 标签内只支持 androd:layout_开头的属性,比如android:background就不支持; android:id是个特例,如果<include android:id@+id/new_bg> (include标签中包含了id),被包含的根元素也包含了布局,那么以<include android:id@+id/new_bg> 指定的id为准 <merge> :如果两个vertical LinearLayout嵌套,那么就有一个是多余的,那么可以使用<merge> 代替<LinearLayout>,一般和<include>标签结合使用,去掉被包含的布局的根布局。 <ViewStub> : 继承了view,宽高都是0,按需加载(例如:没有网络,那么布局就没必要展示,只展示一个错误页就好) 使用方法: <ViewStub android:id="@+id/stub_import"//自己的di android:InFlatedId="@+id/panel_import"//根布局id android:width="wrap_content" android:height="wrap_content" /> 加载: ((ViewStub)findViewById(R.id.stub_import)).setVisibility(View.Visible); 或者 ((ViewStub)findViewById(R.id.stub_import)).inflate(); 这两个方法的作用都是1.去掉ViewStub2.还原布局(因为ViewStub的布局高宽为0,所以要去掉)验证:需要寻找一个能够查看布局性能的工具,分别使用上述方法和普通实现方法,测试是否真的优化了布局,节省了cpu
15.1.2绘制优化
原理:避免的onDraw方法中执行大量操作 1.在onDraw中不要new(不要创建新的局部对象);(原因:onDraw调用频繁,每调用一次就new一次到堆内存中, 结果就是:1.占内存2.频繁gc(降低了程序的执行效率))解决方案:实在要new在onDraw方法外面new,实现单例。 2.在onDraw中不要做耗时和循环操作 (扩展:google优化标准:view绘制帧率<60fps,即:每帧的绘制时间<=16ms(16ms = 1000/60))
15.1.3内存泄露优化
优化方案: 1.避免写出内存泄露的代码 2.通过分析工具(比如MAT)找出潜在的内存泄露 场景: 1.静态变量导致 1.1赋值给静态变量 static Context context = this; 1.2被静态变量引用 static View v = new View(this); 结果:activity无法正常销毁 2.单例模式导致 单例模式的生命周期和application保持一致,(因为得到单例也是static,程序不退出static永远在堆内存中) 如果在Test.getInstance().registerListener(this) 那么如果没有调用解注册的方法(remove(Listener)),那么activity就会一直被单例持有,得不到释放。 3.属性动画导致 属性动画有一种无限循环的动画,如果在onDesdroy没有去停止动画, 结果:这个时候activity的view会被动画持有;view又 持有了activity,导致activity无法释放 解决方案:在desdroy 中animator.cancel();
15.1.4响应速度优化和ANR日志分析
响应速度优化的核心思想:避免在主线程中做耗时操作 解决方案:耗时放在线程中执行(即异步执行) ANR的原因: 1.5秒无响应 (即:5秒内无法响应屏幕触摸事件;5秒内无法响应键盘输入事件) 2.BroacastReceiver10秒内还未执行完操作 定位ANR的问题: ANR发生后,系统会在程序的“程序包名/data/anr”创建一个文件traces.txt。分析这个文件可以定位到原因
15.1.5listview和bitmap优化
listview方案(三个方面): 1.采用viewHolder重用 2.避免在getView中执行耗时操作 3.根据列表的滑动状态来控制任务的执行频率(例如:快速滑动,不适合开始大量异步任务,可以尝试开启硬件加速使listview更流畅。) bitMap方案: 通过BitmapFactory.options对图片采样,通过inSampleSize参数控制图片的高和宽
15.1.6线程优化
方案: 采用线程池 线程池的好处: 1.可以重用内部线程,避免线程的创建和销毁带来的性能开销 2.线程池可以控制线程池的最大并发数,避免大量的线程抢占系统资源造成阻塞 使用: 采用线程池,不要每次都new Tread对象
15.1.7性能优化建议
1.避免创建过多的对象 2.不要过多的使用枚举,枚举占用的内存空间要比整型大 3.常量请使用static final来修饰 4.使用一些Android特有的数据结构,比如SparseArray 和 Pair ,他们都具有更好的性能 5.适当使用软引用和弱引用 6.采用内存缓存和磁盘缓存 7.尽量采用静态内部类,这样可以避免潜在的由于内部类而导致的内存泄露
15.2内存泄露分析与MAT工具
15.3提高程序的可维护性
1、命名要规范 2、代码的排版 3、只为非常关键的代码加注释