Android效能優化

猥瑣發育_別浪發表於2018-07-20

Android效能優化

一、佈局優化:

1、優化方式:

  • 減少不必要巢狀,儘可能使用LinearLayout、ConstraintLayout等控制元件
  • 減少顏色覆蓋,子控制元件背景足夠,不要在其父控制元件加顏色
  • 使用include、merge、ViewStub
    • include:佈局複用
    • merge:去除多餘層級
    • ViewStub:按需載入,當呼叫setVisibility或者inflate方法時才將佈局載入到記憶體中

2、檢查方式:

一般開啟開發者選項中,調戲GPU過渡繪製的按鈕,通過檢視佈局顏色深度來檢查過渡繪製的情況

Android效能優化

二、繪製優化:

每幀繪製時間不超過16ms
1、優化方式:

  • 減少在onDraw方法做耗時操作(迴圈等)
  • 大量建立區域性物件,因為onDraw會頻繁呼叫,導致產生大量臨時物件,引起過多佔用記憶體和頻繁GC

三、記憶體優化:

  • 避免記憶體洩漏的出現
  • 執行緒優化:使用執行緒池
  • 壓縮Bitmap
  • 不要通過Intent傳遞大資料(1MB)
  • 頁面退出時注意清理動畫、回收圖片資源等 1、記憶體洩漏
    無用物件的記憶體得不到及時釋放。因為長生命週期的物件持有短生命週期的引用,導致短生命週期的物件無法被回收。

2、常見記憶體洩漏:

  • 集合物件洩漏
  • 靜態變數、單例持有物件
  • 非靜態內部類、匿名內部類持有外部類引用
  • 資源未關閉

3、舉例說明:

(1) 靜態集合:

public static List<Object> sObjects = new ArrayList<>();

public void newList(){
    for (int i = 0; i < 100; i++) {
        sObjects.add(new Object());
    }
}
複製程式碼

靜態集合只有多個物件,導致沒法被回收
解決方式:使用完畢後將集合清理

 sObjects.clear();
 sObjects = null;
複製程式碼

(2)單例:

public class SingleInstance {
    private static SingleInstance sInstance;
    private Context mContext;

    private SingleInstance(Context context){
        this.mContext = context;
    }

    public static synchronized SingleInstance getInstance(Context context) {
        if (sInstance == null) {
            return new SingleInstance(context);
        }
        return sInstance;
    }
}
複製程式碼

單例生命週期為全域性的,如果傳入的Context為Activity,導致Activity無法回收。
解決方式:使用ApplicationContext

public static synchronized SingleInstance getInstance(Context context) {
        if (sInstance == null) {
            return new SingleInstance(context.getApplicationContext());
        }
        return sInstance;
    }
複製程式碼

(3)、靜態、匿名內部類:

public class HandleActivity extends Activity{

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    class MyHandler extends Handler{
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            
        }
    }
}
複製程式碼

常用的建立一個Handler子類,為非靜態內部類,會持有外部類(Activity)的引用,導致Activity無法被回收。
解決方式:將MyHandler改為靜態內部類,自動不會持有外部類的應用。
可能的問題:如果需要在Handler持有Activity(例如更新UI)
處理方式:使用弱引用(GC的時候無論是否被持有都會被回收),根據實際應用場景使用。

static class MyHandler extends Handler{
    //使用弱引用,GC的使用Activity可被回收
    WeakReference<HandleActivity> activity;

    MyHandler(HandleActivity activity) {
        this.activity = new WeakReference<>(activity);
    }
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
    }
}
複製程式碼

(4)資源未關閉:

  • 網路、檔案流、資料庫Cursor等
  • 廣播取消註冊,EventBus取消註冊等

4、洩漏檢查方式:
可整合LeakCanary檢測、使用Memory Monitor或者使用Android studio中的Android Profiler檢測。

四、響應速度優化:

1、應用啟動初始化:

  • 減少在Application所做的初始化操作,根據業務邏輯可以將統計事件、廣告等SDK的初始化的操作移動啟屏的Activity中。
  • 部分SDK可通過非同步執行緒進行初始化
  • 如果存在多程式的情況,Application會多次例項化,只在主進行中進行初始化操作

2、避免ANR的出現

  • 不要在Service中做耗時操作,可使用IntentService(執行緒、自動銷燬)
  • 不要在BroadcastReceiver的onReceiver中執行耗時操作,可建立IntentService完成

相關文章