成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Android代碼優化小技巧總結

移動開發
這篇文章主要是介紹了一些小細節的優化技巧,當這些小技巧綜合使用起來的時候,對于整個Android App的性能提升還是有作用的,只是不能較大幅度的提升性能而已。選擇合適的算法與數據結構才應該是你首要考慮的因素,在這篇文章中不會涉及這方面。你應該使用這篇文章中的小技巧作為平時寫代碼的習慣,這樣能夠提升代碼的效率。

前言

這篇文章主要是介紹了一些小細節的優化技巧,當這些小技巧綜合使用起來的時候,對于整個Android App的性能提升還是有作用的,只是不能較大幅度的提升性能而已。選擇合適的算法與數據結構才應該是你首要考慮的因素,在這篇文章中不會涉及這方面。你應該使用這篇文章中的小技巧作為平時寫代碼的習慣,這樣能夠提升代碼的效率。

[[148948]]

代碼性能優化建議

通常來說,高效的代碼需要滿足下面兩個規則:

  • 不要做冗余的動作
  • 如果能避免,盡量不要分配內存

代碼的執行效果會受到設備CPU,設備內存,系統版本等諸多因素的影響。為了確保代碼能夠在不同設備上都運行良好,需要***化代碼的效率。

避免創建不必要的對象

雖然GC可以回收不用的對象,可是為這些對象分配內存,并回收它們同樣是需要耗費資源的。 因此請盡量避免創建不必要的對象,有下面一些例子來說明這個問題:

  • 如果你需要返回一個String對象,并且你知道它最終會需要連接到一個StringBuffer,請修改你的實現方式,避免直接進行連接操作,應該采用創建一個臨時對象來做這個操作.
  • 當從輸入的數據集中抽取出Strings的時候,嘗試返回原數據的substring對象,而不是創建一個重復的對象。
  • 一個稍微激進點的做法是把所有多維的數據分解成1維的數組:
  • 一組int數據要比一組Integer對象要好很多。可以得知,兩組1維數組要比一個2維數組更加的有效率。同樣的,這個道理可以推廣至其他原始數據類型。
  • 如果你需要實現一個數組用來存放(Foo,Bar)的對象,嘗試分解為Foo[]與Bar[]要比(Foo,Bar)好很多。(當然,為了某些好的API的設計,可以適當做一些妥協。但是在自己的代碼內部,你應該多多使用分解后的容易。
  • 通常來說,需要避免創建更多的對象。更少的對象意味者更少的GC動作,GC會對用戶體驗有比較直接的影響。

選擇Static而不是Virtual

如果你不需要訪問一個對象的值域,請保證這個方法是static類型的,這樣方法調用將快15%-20%。這是一個好的習慣,因為你可以從方法聲明中得知調用無法改變這個對象的狀態。

常量聲明為Static Final

先看下面這種聲明的方式


  1. static int intVal = 42
  2. static String strVal = "Hello, world!"

編譯器會在類***被使用到的時候,使用初始化方法來初始化上面的值,之后訪問的時候會需要先到它那里查找,然后才返回數據。我們可以使用static final來提升性能:


  1. static final int intVal = 42
  2. static final String strVal = "Hello, world!"

這時再也不需要上面的那個方法來做多余的查找動作了。 所以,請盡可能的為常量聲明為static final類型的。

避免內部的Getters/Setters

像C++等native language,通常使用getters(i = getCount())而不是直接訪問變量(i = mCount).這是編寫C++的一種優秀習慣,而且通常也被其他面向對象的語言所采用,例如C#與Java,因為編譯器通常會做inline訪問,而且你需要限制或者調試變量,你可以在任何時候在getter/setter里面添加代碼。 然而,在Android上,這是一個糟糕的寫法。Virtual method的調用比起直接訪問變量要耗費更多。那么合理的做法是:在面向對象的設計當中應該使用getter/setter,但是在類的內部你應該直接訪問變量。 沒有JIT(Just In Time Compiler)時,直接訪問變量的速度是調用getter的3倍。有JIT時,直接訪問變量的速度是通過getter訪問的7倍。 請注意,如果你使用ProGuard, 你可以獲得同樣的效果,因為ProGuard可以為你inline accessors.

使用增強的For循環寫法

請比較下面三種循環的方法:


  1. static class Foo { 
  2.     int mSplat; 
  3.  
  4. Foo[] mArray = ... 
  5.  
  6. public void zero() { 
  7.     int sum = 0
  8.     for (int i = 0; i < mArray.length; ++i) { 
  9.         sum += mArray[i].mSplat; 
  10.     } 
  11.  
  12. public void one() { 
  13.     int sum = 0
  14.     Foo[] localArray = mArray; 
  15.     int len = localArray.length; 
  16.  
  17.     for (int i = 0; i < len; ++i) { 
  18.         sum += localArray[i].mSplat; 
  19.     } 
  20.  
  21. public void two() { 
  22.     int sum = 0
  23.     for (Foo a : mArray) { 
  24.         sum += a.mSplat; 
  25.     } 

zero()是最慢的,因為JIT沒有辦法對它進行優化。

one()稍微快些。

two() 在沒有做JIT時是最快的,可是如果經過JIT之后,與方法one()是差不多一樣快的。它使用了增強的循環方法for-each。
所以請盡量使用for-each的方法,但是對于ArrayList,請使用方法one()。

使用包級訪問而不是內部類的私有訪問

參考下面一段代碼


  1. public class Foo { 
  2.     private class Inner { 
  3.         void stuff() { 
  4.             Foo.this.doStuff(Foo.this.mValue); 
  5.         } 
  6.     } 
  7.  
  8.     private int mValue; 
  9.  
  10.     public void run() { 
  11.         Inner in = new Inner(); 
  12.         mValue = 27
  13.         in.stuff(); 
  14.     } 
  15.  
  16.     private void doStuff(int value) { 
  17.         System.out.println("Value is " + value); 
  18.     } 

我們定義了一個私有的內部類(Foo$Inner),它直接訪問了外部類中的私有方法以及私有成員對象。這是合法的,這段代碼也會如同預期一樣打印出”Value is 27”。

問題是,VM因為Foo和(Foo.Inner)是不同的類,會認為在 (Foo.Inner)中直接訪問Foo類的私有成員是不合法的。即使Java語言允許內部類訪問外部類的私有成員。為了去除這種差異,編譯器會產生一些仿造函數:


  1. /*package*/ static int Foo.access$100(Foo foo) { 
  2.     return foo.mValue; 
  3. /*package*/ static void Foo.access$200(Foo foo, int value) { 
  4.     foo.doStuff(value); 

每當內部類需要訪問外部類中的mValue成員或需要調用doStuff()函數時,它都會調用這些靜態方法。這意味著,上面的代碼可以歸結為,通過accessor函數來訪問成員變量。早些時候我們說過,通過accessor會比直接訪問域要慢。所以,這是一個特定語言用法造成性能降低的例子。

如果你正在性能熱區(hotspot:高頻率、重復執行的代碼段)使用像這樣的代碼,你可以把內部類需要訪問的域和方法聲明為包級訪問,而不是私有訪問權限。不幸的是,這意味著在相同包中的其他類也可以直接訪問這些域,所以在公開的API中你不能這樣做。

避免使用float類型

Android系統中float類型的數據存取速度是int類型的一半,盡量優先采用int類型。

使用庫函數

盡量使用System.arraycopy()等一些封裝好的庫函數,它的效率是手動編寫copy實現的9倍多。

Tip: Also see Josh Bloch’s Effective Java, item 47.

謹慎使用native函數

當你需要把已經存在的native code遷移到Android,請謹慎使用JNI。如果你要使用JNI,請學習JNI Tips

關于性能的誤區

在沒有做JIT之前,使用一種確切的數據類型確實要比抽象的數據類型速度要更有效率。(例如,使用HashMap要比Map效率更高。) 有誤傳效率要高一倍,實際上只是6%左右。而且,在JIT之后,他們直接并沒有大多差異。

關于測量

上面文檔中出現的數據是Android的實際運行效果。我們可以用Traceview 來測量,但是測量的數據是沒有經過JIT優化的,所以實際的效果應該是要比測量的數據稍微好些。

責任編輯:倪明 來源: 安卓培訓
相關推薦

2015-09-16 14:47:14

Android性能優化代碼

2022-11-24 10:34:05

CSS前端

2022-03-10 08:01:06

CSS技巧選擇器

2009-11-26 10:32:57

PHP代碼優化

2009-06-18 11:12:42

Hibernate S優化

2019-02-25 07:07:38

技巧React 優化

2022-07-20 08:21:00

Java代碼優化

2024-09-14 11:23:19

2022-07-04 08:51:43

條件語句JavaScript

2023-11-05 19:46:56

JavaIntelliJ代碼

2017-03-02 10:30:57

AndroidAndroid Stu技巧

2010-01-27 17:45:15

Android應用技巧

2012-07-23 10:22:15

Python性能優化優化技巧

2011-05-10 17:06:05

SEO

2021-03-25 15:19:33

深度學習Pytorch技巧

2020-01-16 18:30:07

技術SQL優化

2011-06-14 11:14:10

性能優化代碼

2017-12-04 12:29:15

前端JavaScript性能優化

2022-11-29 10:42:46

GoFrame技巧腳手架

2025-04-09 00:01:05

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: www.v888av.com | 日本五月婷婷 | 超碰国产在线 | v片网站 | 日韩欧美国产一区二区三区 | 亚洲欧美日韩电影 | 日韩国产三区 | 免费av手机在线观看 | 亚洲一区在线日韩在线深爱 | 国产一区二区三区四区三区四 | 欧美日韩精品一区二区三区四区 | 免费毛片网站 | 日韩一区二区三区在线视频 | 久久91精品国产一区二区 | 亚洲精品国产成人 | 久久久91精品国产一区二区三区 | 夜色www国产精品资源站 | 国产日韩欧美一区二区在线播放 | 欧美成视频在线观看 | 欧美成人激情 | 久久精品日产第一区二区三区 | 欧美黄色网 | 日韩精品视频一区二区三区 | 国产成人99久久亚洲综合精品 | 久久久久久久久久久蜜桃 | 久久久久91 | 欧美日韩精品专区 | 日韩精品在线观看一区二区三区 | 日日夜夜免费精品 | 中文字幕av在线 | 色综合久 | 久久精品国产一区二区电影 | 久草视频在线看 | 91亚洲国产| 久久一级| 中文字幕日韩欧美一区二区三区 | 亚洲国产精品第一区二区 | 亚洲一区二区在线播放 | 日韩毛片在线免费观看 | 国产精品一区二区三区在线 | 美国a级毛片免费视频 |