Android程序性能优化
主要从三个方面:
1.UI优化
2.提高线程的并发
3.内存方面:从防止内存泄漏和内存浪费两个
UI
- 布局文件
1.减少布局的层级:
举例,自定义ViewGroup如果需要使用布局文件,布局文件里使用取代XXXLayout,可以减少一层布局;
2.减少使用match_parent,ViewGroup尽量少用wrap_content,控件的宽高尽量使用固定值
这样可以减少measure,layout过程的计算的复杂度
如果某个ViewGroup有10个子View,ViewGroup宽高设置了wrap_content,10个子View中5个宽高设置了固定值,
另外五个设置了match_parent,
在mearsure过程中,mearsure事件传入ViewGroup,ViewGroup遍历10个子View,把measure事件传给它们, 得
到宽高结果返回给ViewGroup,ViewGroup根据结果获得最大的宽,最大的高,再把最大的宽和高传给那
五个子View
如果都设置成固定值,就可以measure中反复遍历的过程
3.ViewStub 用懒加载的方式
提高程序中的线程并发性
- 对共享资源的处理
当多线程对同一资源操作时会产生线程安全的问题:
根据共享资源的情况:
1.如果共享资源是boolean,Integer这种基本数据类型,
可以采用volatile或volatile+AutomicXXX(如AutuomicInteger)的方式保证并发的线程安全;
volatile可以保证线程对共享资源的原子操作,对其他的线程具备可见性;
当共享资源的操作有非原子性操作时,用AutomicXXX封装共享资源;
2.如果共享资源是对象,
使用sychronized或lock,保证读并发,写同步
在某个线程进行写操作时,通过修改标志位的方式,使得后面的读写线程阻塞,当该线程完成写操作之
后,将阻塞的线程通过系统唤醒,
线程的阻塞和唤醒,可以通过wait-notify实现。
3.如果共享资源是集合的话,
Java提供了CopyOnWrite,Concurrent,Blocking三种策略提高并发性,实现读写分离,读并发,写同步:
1.CopyOnWrite, 用于读多写少的情况,利用写时复制,提高了写时读并发
2.Concurrent, 使用分段锁的方式,不同分段的读写并发,相同分段的读并发,写同步
3.Blocking, 解决限制容量的容器的存取问题,类似生产者消费者模式,
容器为空时,取线程阻塞,直到容器不为null,线程会被唤醒
容器满时,存线程阻塞,直到容器不满,线程会被唤醒 - 根据具体情况选择使用ThreadPool,还是new Thread
如果任务只是偶尔要在子线程中运行,采用new Thead;
如果任务经常需要在子线程中运行,采用ThreadPool;
内存
避免内存浪费
-
选择合适的数据结构
1.ArrayMap,SparseMap是Android为了内存优化提供的HashMap的替代品;
2.ArrayList多次删除后,可以使用trimToSize()减少ArrayList封装的数组的Length; -
缓存
缓存分为两类:
1.缓存空对象,
当需要对象时,从缓存中取出空对象;
当对象使用完成后,将对象数据清空,放入缓存;
这样做的目的是需要经常创建某个类的对象时,可以采用这种缓存,减少new和GC
举例,ThreadPool, Message.obtain都是采用了这种缓存
2.缓存带有数据的对象,
Glide中针对Bitmap的缓存
OKHttp中针对Request-Response,Connection长链接的缓存
避免内存泄漏
1.使用软弱引用
2.当遇到使用传统的观察者模式时,
例如,EventBus,BroadcastReceiver,在销毁或置空观察者或被观察者时,一定先要解除两者之间的绑定关系
3.做到对象与对象之间的解藕
通过方法传入的对象,不要保存它的全局引用
Class A {
methodA() {... }
}
Class B {
A a;
B(A a) {
this.a = a;
}
methodB() {
a.methodA();
}
}
A a = new A();
B b = new B(a);
a = null;
虽然a = null,但仍有引用指向A对象
class A {
methodA() {....}
}
class B {
methodB(A a) {
a.methodA();
}
}
这样,A与B解耦,
可以把methodA,methodB抽象
new B() {
void methodB(A a) {
a.methodA();
}
}.methodB(new A() {
void methodA() {
... ...
}
});
而传统的观察者模式
class Observer {
void update() {
}
}
class Observable {
List<Observer> observers;
void register(Observer oberser) {
observers.add(oberser);
}
void unregister(Observer oberser) {
observers.remove(oberser);
}
void update() {
for(Observer obs: observers) {
obs.upate();
}
}
}
这样很容易造成内存泄漏,
RxJava实际上,使用了多种方式实现了Observer与Observable之间的解耦