首先删除布局中无用的控件和层级,其次有选择地使用性能较低的ViewGroup
在CPU的使用度上,RelativeLayout使用的时间比LinearLayout要多。因此,如果能使用LinearLayout的话,就不要使用RelativeLayout。不过大多数的时候,单独使用一种布局无法完成界面的部署,因此需要通过“嵌套”的方式来完成。
如果不得已使用嵌套布局的话,建议采用RelativeLayout,因为ViewGroup的嵌套就相当于增加了布局的层数,同样会降低程序的性能。
另外一种手段是采用
ViewStub提供了按需加载的功能
绘制优化是指onDraw方法要避免执行大量的操作。
1、静态变量导致的内存泄露
在dalvik虚拟机中,static变量所指向的内存引用,如果不把它设置为null,GC是永远不会回收这个对象的。
public class MainActivity extends Activity{
public static Context mContext;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
}
}
解决办法:在onDestroy()方法中将mContext = null; 处理。
2、单例模式导致的内存泄漏
public class SingletonA {
private static SingletonA mSingletonA;
public static SingletonA getInstance(){
if (mSingletonA == null) {
return new SingletonA();
}
else
return mSingletonA;
}
//constructor
public SingletonA(){}
//other methods
}
接下来在Activity中对这个类进行使用:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SingletonA instanceF = SingletonA.getInstance(this);
//在当前代码中使用this将此activity的实例给了静态变量,导致activity退出以后无法被释放
}
3、属性动画导致的内存泄露
从Andorid 3.0开始出现属性动画,属性动画中有一类无限循环的动画,如果不在onDestroy中去停止动画,那么动画会一直播放下去,尽管已经无法在界面上看到动画效果了,并且这个时候Activity的View会被动画持有,而View又持有了Activity,最终Activiy无法释放。
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mButton = findViewById(R.id.button);
ObjectAnimator animator = ObjectAnimator.ofFloat(mButton,"rotation",0,360).setDuration(2000);
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.start();
}
解决方法是在Activity的onDestroy中调用animator.cancel()来停止动画。
Android规定,Activity在5秒内无法响应屏幕触摸事件或者键盘输入事件出现ANR。BroadcastReceiver在10秒内未执行操作会出现ANR。
定位ANR:在/data/anr目录下的文件traces.txt,通过分析这个文件能定位ANR的原因。
如下面的代码:
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(Runnable.layout.activity_main);
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
testANR();
}
}).start();
SystemClock.sleep(10);
initView();
}
private synchronized void testANR(){
}
private synchronized void initView(){
}
虽然testANR()和initView()不在同一个线程上,但是因为他们都要获取同一个对象的锁(this),因此也会发生子线程与主线程抢同一个锁的情况。
ListView:
1、首先要采用ViewHolder并避免在getView中执行耗时操作
2、其次要根据列表的滑动状态来控制任务的执行频率,比如当列表快速滑动时显然是不太适合开启大量的异步任务的。
3、尝试开启硬件加速来使ListView的滑动更加流畅。