android性能優化

    android設備作爲一種移動設備,不管是內存還是CPU的性能都收到了一定的限制,無法做到像PC設備那樣具有超大的內存和高性能的CPU。鑑於這一點,這也意味着android程序不可能無限制的使用內存和CPU資源,過多的使用內存會導致程序內存溢出,即OOM。而過多的使用CPU資源,一般是指做出大量的耗時任務,會導致手機變的卡頓無法響應的情況,即ANR。

  1. 佈局優化

    佈局優化的思想其實很簡單,就是儘量減少佈局文件的層級。
    
  • 進行佈局優化,首先刪除佈局中無用的控件和層級,其次有選擇的使用性能較低的viewGroup,比如RelativeLayout。如果佈局中既可以使用LinearLayout也可以使用RelativeLayout,那麼就採用LinearLayout,這是因爲RelativeLayout功能比較複雜,它的佈局過程需要花費更多的CPU。
  • 佈局優化的另一種手段就是採用 < include>標籤、< merge>標籤和ViewStub.
    < include> 標籤可以將一個指定的佈局文件加載到當地的文件中。需要注意的是,如果在佈局文件中的根元素中設置了ID,而在< include>也設置了id,以標籤中的屬性爲準。
    < merge>標籤一般和< include>標籤一起使用從而減少佈局的層級。如果當前佈局文件中存在一個LinearLayout,而被包含的佈局文件中也使用了LinearLayout,那麼顯然被包含的是多餘的,通過< merge>標籤可以去掉多餘的這一層LinearLayout。
    ViewStub繼承了View,它非常輕量級而且寬、高都是0,因此它本身不參與任何的佈局繪製過程。ViewStub的意義在於按需加載所需的佈局文件,在實際開發中,很多佈局文件不會在正常情況不會顯示,比如網絡異常的界面,這個時候就沒必要在初始化的時候,就把該界面加載進來,通過ViewStub就可以做到在使用的時候再加載,提高了程序初始化的性能。
  <ViewStub
        android:id="@+id/stub_import"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout="@layout/layout_network_error"
        />

以下面兩種方式進行:

findViewById(R.id.stub_impout).setVisibility(View.VISIBLE);

當ViewStub通過setVisibility方法加載後,ViewStub就會被它內部的佈局替換掉,這個時候ViewStub就不再是整個佈局結構中的一部分了。另外,目前ViewStub還不支持< merge>標籤。

  1. 繪製優化
    繪製優化是指View的onDraw方法要避免執行大量的操作,這主要體現在兩個方面。
  • 首先,onDraw中不要創建新的局部現象,這是因爲onDraw方法可能會被頻繁調用,這樣就會在一瞬間產生大量的臨時對象,這不僅佔用了過多的內存而且還會導致系統更加頻繁GC,降低了程序的執行效率。
  • onDraw方法中不要做耗時的任務,也不能執行成千上萬的循環操作,儘管每次循環都很輕量級,但是大量的循環仍然十分搶佔CPU的時間片,這會照成View的繪製的不流暢。按照Google官方給出的性能優化典範中的標準,View的繪製幀率保證60fps都是最佳的,這就要求每幀的繪製時間不超過16ms(16ms = 1000/60),雖然程序很難保證16ms這個時間,但是儘量降低onDraw方法的複雜度總是切實有效的。
  1. 內存泄露優化
  • 內存泄漏
    3.1 靜態變量導致的內存泄漏
        下面代碼引用了靜態mContext,導致Activity不能正常銷燬,導致內存泄漏。
		public class MainActivity extends Activity {
		    private static final String TAG = "MainActivity";
		    private static Context context;
		    @Override
		    protected void onCreate(Bundle saveInstanceState){
		        super.onCreate(saveInstanceState);
		        setContentView(R.layout.activity_main);
		        context = this;
		    }
		}

   3.2 單例模式導致的內存泄漏
      靜態變量導致的內存泄漏都比較明顯,相應的單例模式帶來的內存泄漏是容易讓我們忽視的。
示例代碼如下:

public class SingleInstance {
    private Context mContext;
    private static SingleInstance instance;
 
    private SingleInstance(Context context) {
        this.mContext = context;
    }
 
    public static SingleInstance getInstance(Context context) {
        if (instance == null) {
            instance = new SingleInstance(context);
        }
        return instance;
    }
 
    public void say() {
        Log.i("tag", "this is single instance");
        Log.i("tag", ":code:" + instance.hashCode());
    }

很明顯的原因在於引用的context對象,當在程序中被activity調用了,恰巧activity先被銷燬的情況下,因爲一直在被static所修飾的類引用,會造成內存中不能被銷燬,導致內存泄漏。
解決辦法是可以將應用的ApplicationContext賦值給SingleInstance 的Context

public static SingleInstance getInstance(Context context) {
        if (instance == null) {
            instance = new SingleInstance(context.getApplicationContext());
        }
        return instance;
    }

   3.3 屬性動畫導致的內存泄漏
      從android3.0開始,Google提供了屬性動畫,屬性動畫中有一類無限循環的動畫,如果在activity播放此類動畫且沒有在onDestory中去停止動畫,那麼動畫會一直播放下去,儘管已經無法在界面上看到動畫效果了,並且這個時候Activity的View會被動畫持有,而View又持有了Activity,最終Activity無法釋放。
4. 響應速度優化
      響應速度優化的核心思想是避免主線程中耗時操作。android中規定,activity如果5秒鐘10秒鐘之內還未執行完操作也會出現ANR。
5. 線程優化
      線程優化的思想就是線程池,避免程序中存在大量的Tread。線程池可以重用內部的線程,從而避免的線程的創建和銷燬帶來的性能開銷,同時線程池還能有效的控制線程池的最大併發數,避免大量的線程因相互搶佔資源從而導致阻賽現象的對象。
6. 電池電量優化

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章