騰訊,阿里,百度Android高級崗;全方位性能調優技術體系詳解

前言

不少人對大廠的印象是;面試造飛機,工做擰螺絲。java

用造飛機的能力去擰螺絲,形象的說明了大廠裏的技術標準是遠高於在小公司搬代碼的。在具有java語言,設計模式,數據結構算法技能能基礎之上,性能調優是關鍵點面試

這篇文章但願給你們介紹一下目前那些一線公司Android開發中性能調優最經常使用的方法,後面會再把那些性能調優的技術解析文章分享給你們,歡迎持續關注~算法

全方位性能優化方法

1,佈局優化

佈局優化的思想很簡單,就是儘可能減小布局文件的層級,佈局中的層級少了,這就意味着Android繪製時的工做量少了,那麼程序的性能天然就高了。
那麼如何進行佈局優化呢?有如下兩點:
•首先刪除佈局中無用的看控件和層級,其次有選擇地使用性能較低的ViewGroup,好比RelativeLayout。
•能夠採用標籤、標籤、ViewStub。標籤主要用於佈局重用,標籤通常配合標籤使用,它能夠下降減小布局的層級,而ViewStub則提供了按需加載的功能。設計模式

2,繪製優化

繪製優化是指View的onDraw方法要避免執行大量的操做,主要體如今兩個方面
•onDraw中不要建立新的局部對象,這是由於onDraw方法可能會被頻繁調用,這樣就會在一瞬間產生大量的臨時對象,這不只佔用了過多的內存並且還會致使系統會更頻繁gc,下降程序的執行效率。
•onDraw方法中不要作耗時的任務,也不能執行成千上萬次的循環操做,儘管每次循環都很輕量級,可是大量的循環仍然十分搶佔CPU的時間片,這會形成View的繪製過程很不流暢。緩存

3,內存優化

內存泄露在開發過程當中是一個須要重視的問題,內存優化分爲兩個方面,一方面是在開發過程當中避免寫出有內存泄露的代碼,另外一方面是經過一些分析工具好比MAT來找出潛在的內存泄露繼而解決。
場景1:靜態變量致使內存泄露
好比下面這段代碼:性能優化

public class MainActivity extends Activity {
    private static final String TAG = "MainActivity";
    private static Context sContext;
    private static View sView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        sContext = this;
        sView = new View(this);
    }
}
複製代碼

MainActivity沒法正常銷燬,由於靜態變量sContext引用了它。一樣,sView是一個靜態變量,他內部持有了當前Activity,因此Activity仍然沒法釋放。
場景2:單例模式致使內存泄露
靜態變量致使的內存泄露都太過明顯了,但單例模式所帶來的內存泄露是咱們容易忽視的。好比下面這段代碼:markdown

public class TestManager {

    private List<OnDataArrivedListener> mOnDataArrivedListeners = new ArrayList<OnDataArrivedListener>();

    private static class SingletonHolder {
        public static final TestManager INSTANCE = new TestManager();
    }

    private TestManager() {
    }

    public static TestManager getInstance() {
        return SingletonHolder.INSTANCE;
    }

    public synchronized void registerListener(OnDataArrivedListener listener) {
        if (!mOnDataArrivedListeners.contains(listener)) {
            mOnDataArrivedListeners.add(listener);
        }
    }

    public synchronized void unregisterListener(OnDataArrivedListener listener) {
        mOnDataArrivedListeners.remove(listener);
    }

    public interface OnDataArrivedListener {
        public void onDataArrived(Object data);
    }
}
複製代碼

首先提供一個單例模式的TestManager,TestManager能夠接收外部的註冊並將外部的監聽器存儲起來。而後用Activity實現OnDataArrivedListener接口並向TestManager註冊監聽,可是若是缺乏解註冊的操做,會引發內存泄露。好比下面這段代碼:數據結構

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TestManager.getInstance().registerListener(this);
    }
複製代碼

Activity的對象被單例模式的TestManager所持有,而單例模式的特色是其生命週期和Application保持一致,所以Activity對象沒法被及時釋放。
場景3:屬性動畫致使的內存泄露
從Android3.0開始,Google提供了屬性動畫,屬性動畫中有這麼一類無限循環的動畫,若是在Activity中播放此類動畫且沒有在onDestroy中中止動畫,那麼動畫就會一直播放下去,儘管已經沒法在界面上看到動畫效果,但這個時候Activity的View會被動畫持有,而View又持有了Activity,最終Activity沒法釋放。架構

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ObjectAnimator animator = ObjectAnimator.ofFloat(mButton, "rotation",0, 360).setDuration(2000);
        animator.setRepeatCount(ValueAnimator.INFINITE);
        animator.start();
        //animator.cancel();
    }
複製代碼
4,響應速度優化和ANR日誌分析

響應速度優化的核心思想是避免在主線程中作耗時操做,可是有時候的確有不少耗時操做,怎麼辦呢?能夠將這些耗時操做放在線程中去執行,即採用異步的方式執行耗時操做。響應速度過慢更多地體如今Activity的啓動速度上面,若是在主線程中作太多的事情,會致使Activity啓動出現黑屏現象,甚至出現ANR。Android規定,Activity若是5秒鐘以內沒法響應屏幕觸摸事件或者鍵盤輸入事件就會出現ANR,而BroadcastReceiver若是10秒以內還未執行完操做也會出現ANR,那麼在實際開發過程當中遇到ANR,怎麼定位問題呢?其實當一個進程發生ANR了之後,系統會在/data/anr/目錄下建立一個文件traces.txt,經過分析這個文件就能定位出ANR的緣由。好比下面代碼在Activity的onCreate中休眠30s,程序運行持續點擊屏幕,應用必定會出現ANR:併發

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        SystemClock.sleep(30 * 1000);
    }
複製代碼
5,ListView和Bitmap優化

ListView優化三個方面:
•採用ViewHolder並避免在getView中執行耗時操做
•根據列表的滑動狀態來控制任務的執行頻率,好比當列表快速滑動時顯然是不太適合開啓大量異步任務的。
•嘗試開啓硬件加速來使ListView的滑動更加流暢。
Bitmap優化,主要是經過BitmapFactory.Options來根據須要對圖片進行採樣,採樣過程當中主要用到了BitmapFactory.Option的inSampleSize參數。

6,線程優化

線程優化的思想是採用線程池,避免在程序中存在大量的Thread。線程池能夠重用內部的線程,從而避免了現場的建立和銷燬所帶來的性能開銷,同時線程池還能有效地控制線程池的最大併發數,避免大量的線程因互相搶佔系統資源從而致使阻塞現象發生。

7,其餘性能優化建議

還有一些其餘性能優化的小建議,經過它們能夠在必定程度上提升性能:
•避免建立過多的對象
•不要過多使用枚舉,枚舉佔用的內存空間要比整型大
•常量請用static final來修飾
•使用一些Android特有的數據結構,好比SpareArray和Pair等,它們都具備更好的性能
•適當使用軟引用和弱引用
•採用內存緩存和磁盤緩存
•儘可能採用靜態內部類,這樣能夠避免在的因爲內部類而致使的內存泄露
提升程序的可維護性
主要是提升代碼的可維護性和可擴展性,而程序的可維護性本質上也包含可擴展性。
•命名要規範,要能正確地傳達出變量或者方法的含義,少用縮寫,關於變量的前綴能夠參考Android源碼的命名方式,好比私有方式以m開頭,靜態成員以s開頭,常量則所有用大寫字母表示,等等。
•代碼的排版上須要留出合理的空白區分不一樣的代碼塊,其中同類變量的聲明要放在一組,兩類變量之間要留出一行空白做爲區分。
•僅爲很是關鍵的代碼添加註釋,其餘地方不寫註釋,這就對變量和方法的命名風格提出了很高的要求。
•代碼的層次性指代碼要有分層的概念,對於一段業務邏輯,不要試圖在一個方法或者一個類中去所有實現,它能夠分紅幾個子邏輯,而後每一個子邏輯作本身的事情。單一職責是和層次性相關聯,代碼分紅之後,每一層僅僅關注少許的邏輯,這樣就作到了單一職責。

性能調優技術大綱;

性能優化系列文章;

性能調優;如何讓你的APK瘦身88%!

Android高級性能調優;難以想象的OOM!


BAT主流Android高級架構技術大綱+學習路線+資料分享

架構技術詳解,學習路線與資料分享都在博客這篇文章裏《BATJ一線大廠最主流的Android高級架構技術;體系詳解+學習路線》
(包括自定義控件、NDK、架構設計、混合式開發工程師(React native,Weex)、性能優化、完整商業項目開發等)

  • 阿里P8級Android架構師技術腦圖

  • 全套體系化高級架構視頻;七大主流技術模塊,視頻+源碼+筆記

相關文章
相關標籤/搜索