面试题之---Android性能优化

(一)布局优化

 1,就是尽量减少布局文件的层级.

2,简单的布局能用1个LinearLayout搞定的,就不要用Relativelayout,因为Framelayout和LinearLayout都是一种简单高效的ViewGroup,Relativelayout功能比较复杂,相对来说,布局渲染要花费更多时间.

但若是需要嵌套LinearLayout时,能用Relativelayout就用Relativelayout代替.

3,使用include,merge标签引入布局,或者用Viewstub延时加载.

可以通过手机开发者里面的调试GPU过度绘制来检测布局是否需要优化

 

(二)绘制优化

   绘制优化是指在View的onDrwa()方法里避免执行大量的操作.比如:

      1,不要在onDrwa()方法中创建对象,因为onDrwa()频繁被调用,这样就会产生很多临时对象,这样不近耗内存,还会导致系统频繁GC,降低运行效率.

     2,不要在onDrwa()方法中执行耗时操作.不停的执行onDrwa(),就会有很多耗时任务轮训,造成View绘制不流畅.

 

(三)线程优化

      线程的创建和销毁都比较耗性能,所以线程的优化是采用线程池,线程池的优点:

     1,避免了线程创建销毁带来的消耗

     2,能够有效控制线程池的最大并发数,避免了大量的线程因互相抢占资源从而导致的阻塞现象.

 

(四)内存泄漏优化

   当一个对象已经不需要再使用了,本该被回收时,而有另外一个正在使用的对象持有它的引用从而导致它不能被回收,这导致本该被回收的对象不能被回收而停留在堆内存中,这就产生了内存泄漏。

  不停的内存泄漏,就会导致内存溢出.所以内存泄漏优化分为2个方面来解决:

    A,代码中注意,

    B,上线前通过LeakCanary、MAT等工具来检测

 

在敲代码时就要注意:

 1,静态变量造成的内存泄漏,

public class TestActivity extends Activity {
    public static Context mContext;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mContext this;
    }
}  

        解决方式:变量不用static修饰,或者上下文用Application的上下文.

       2,Handler容易造成内存泄漏,当使用内部类或匿名内部类的方式创建Handler时,Handler对象会隐式地持有一个外部类对象的引用(这里的外部类是Activity)。

   一般在一个耗时任务中会开启一个子线程,如网络请求或文件读写操作,我们会使用到Handler对象。但是,如果在任务未执行完时,Activity被关闭了,Activity已不再使用,此时由GC来回收掉Activity对象。

   由于子线程未执行完毕,子线程持有Handler的引用,而Handler又持有Activity的引用,这样直接导致Activity对象无法被GC回收,即出现内存泄漏。

public class TestActivity extends AppCompatActivity {
    private Handler mHandler new Handler() {
        @Override
        public void handleMessage(Message msg) {
            //...
        
}
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        loadData();
    }
    private void loadData(){
        //...request
        
Message message = Message.obtain();
        mHandler.sendMessage(message);
    }
}

 解决方式:

       2.1,Handler声明为静态内部类。因为静态内部类不会持有外部类的引用,所以不会导致外部类实例出现内存泄露。
       2.2,Handler中添加对外部Activity的弱引用。由于Handler被声明为静态内部类,不再持有外部类对象的引用,导致无法在handleMessage()中操作Activity中的对象,所以需要在Handler中增加一个对Activity的弱引用。

      2.3,这样虽然避免了Activity泄漏,不过Looper线程的消息队列中还是可能会有待处理的消息,所以我们在Activity的Destroy时或者Stop时应该移除消息队列中的消息

public class TestActivity  extends AppCompatActivity {
    private MyHandler mHandler new MyHandler(this);
    private TextView mTextView ;
    private static class MyHandler extends Handler {
        private WeakReference<Context> reference;
        public MyHandler(Context context) {
            reference new WeakReference<>(context);
        }
        @Override
        public void handleMessage(Message msg) {
            TestActivity  activity = (TestActivity ) reference.get();
            if(activity != null){
                activity.mTextView.setText("");
            }
        }
    }

 

@Override
protected void onDestroy() {
    super.onDestroy();
    mHandler.removeCallbacksAndMessages(null);
}

 

        3,资源未及时释放:

   对于使用了BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap等资源的使用,应该在Activity销毁时及时关闭或者注销,否则这些资源将不会被回收,造成内存泄漏。

      4,无限轮训动画造成泄漏:

  解决方式:销毁时,取消动画

animator = ObjectAnimator.ofFloat(btn_home, "ratation"0360).setDuration(2000);
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.start();     

@Override
protected void onDestroy() {
    super.onDestroy();
    animator.cancel();
}

 

 (五)不要使用枚举,枚举占用的内存空间比整型大;使用一些特有的数据结构,比如AparryArray和Pair等,性能更佳.


借鉴资源:

1,任玉刚先生的安卓艺术开发探索

2,Android性能优化之常见的内存泄漏  https://blog.csdn.net/u010687392/article/details/49909477

猜你喜欢

转载自blog.csdn.net/qq_41118173/article/details/80305043