出色的用戶體驗有三個特征:速度快、響應及時以及無縫。下面的信息幫助你的應用如何能夠在Android上實現這些特征。

一、速度快

你不能假設手機與桌面系統和服務器一樣提速,更多的是你要關注你的代碼是否高效。

編寫高效的Android代碼,應遵循兩個原則:

不要做不必要的事

不要分配不必要的內存

以下是一些達到此目標的小技巧(有一些技巧是與oo的原則沖突,斟酌使用場景):

1、避免建立對象

例如,int數組比Integer數組好,同理,這適用于所有基本類型的組合

2、使用本地方法

不要吝惜使用String.indexOf(), String.lastIndexOf()等特殊實現的方法(specialty methods)。這些方法都是使用C/C++實現的

3、使用實現類比接口好

Map myMap1 = new HashMap();

HashMap myMap2 = new HashMap();

調用一個接口的引用會比調用實體類的引用多花費一倍的時間

4、不用getter和setter

應該直接訪問變量

5、將成員變量緩存到本地

for (int i = 0; i< this.mCount; i++)           

    dumpItem(this.mItems[i]);

最好改成這樣:

  int count = this.mCount;

  Item[] items = this.mItems;

  for (int i = 0; i< count; i++) dumpItems(items[i]);

另外,永遠不要在for的第二個條件中調用任何方法

6、給常量加上final

static int intVal = 42;

static String strVal = “Hello, world!”;

  編譯器會生成一個叫做的初始化類的方法,當類第一次被使用的時候這個方法會被執行。方法會將42賦給intVal,然后把一個指向類中常量表的引用賦給strVal。當以后要用到這些值的時候,會在成員變量表中查找到他們。

static final int intVal = 42;

static final String strVal = “Hello, world!”;

  現在,類不再需要方法,因為在成員變量初始化的時候,會將常量直接保存到類文件中。用到intVal的代碼被直接替換成42,而使用strVal的會指向一個字符串常量,而不是使用成員變量。

7、謹慎使用foreach

  foreach可以用在實現了Iterable接口的集合類型上。foreach會給這些對象分配一個iterator,然后調用hasNext()和next()方法。你最好使用foreach處理ArrayList對象,但是對其他集合對象,foreach相當于使用 iterator

8、避免使用枚舉

  枚舉變量非常方便,但不幸的是它會犧牲執行的速度和并大幅增加文件體積

9、將內部類需要訪問的外部變量或方法聲明在包范圍內

public class Foo {

  private int mValue;

  public void run() {

      Inner in = new Inner();

      mValue = 27;

      in.stuff();

  }

  private class Inner {

      void stuff() {

      System.out.println(Foo.this.mValue);

      }

  }

}

Foo$Inner是一個完全獨立的類,它要直接訪問Foo的私有成員是非法的。編譯器會自動生成一個方法:

/*package*/ static int Foo.access$100(Foo foo) {

  return foo.mValue;

}

內部類在每次訪問”mValue”方法時,都會調用這個靜態方法。同理,內部類要訪問私有方法也是如此。

10、避免使用浮點數

嵌入式處理器通常沒有支持浮點運算的硬件,所有對”float”和”double”的運算都是通過軟件實現的

通過將內部類訪問的變量和函數聲明由私有范圍改為包范圍,我們可以避免這個問題。這樣做可以讓代碼運行更快,并且避免產生額外的靜態方法。(遺憾的是,這些成員變量和方法可以被同一個包內的其他類直接訪問,這與經典的OO原則相違背。因此當你設計的時候應該謹慎使用這條優化原則)

二、響應及時

1、將耗時工作交到子線程

2、如果你的程序在后臺處理用戶的輸入,給出一個你正在工作的提示(ProgressBar(進度條)和ProgressDialog(進度對話框)是很好的選擇)

3、如果是游戲,把計算步驟放在子線程中

三、無縫

1、不要丟失數據,繼承onPause()方法

2、利用ContentProvider來共享數據

3、不要打斷用戶,使用通知

隨著手機平臺的發展和所提供應用的提升,質量成為應用成功的最重要因素。如果那些應用無法提供強大的功能和穩定的用戶體驗,那就會很快被用戶卸載。開發者需要記住的是,雖然Android智能手機和平板電腦的速度日益提升,但其應用仍然運行在資源有限的環境中,其電池及處理器性能與最新的臺式電腦、手提電腦仍存在差距。以下是某些優化應用運行效果的方法:
我們先來闡述某些讓應用反應靈敏的編程技巧。

技巧1:從優秀的編程開始

要采用已為用戶所接受的運算法則和標準的設計樣式,這些被人們長期使用的編程法則也同樣適用于Android應用,尤其當這些應用使用內在設備服務時。
比如,假設你編寫的應用需要以地理定位服務為基礎。只需要在必要時開始注冊進行位置更新,在無需更新信息時,確保應用停止更新進程。這會幫助節省設備的電量和系統處理器的負擔。

技巧2:保持應用的靈活性
通過使用AsyncTask、IntentService或自定義背景服務來保持應用的靈活性。使用加載器來簡化加載時間較長數據的狀態管理,比如光標。不可讓應用在其他進程進行時顯得緩慢或完全靜止。
如果某些操作需要一定的時間和資源,應當將這個進程單獨分離出來異步處理,這樣你的應用才能夠保持流暢的運行。可以運用這種方法的操作包括:磁盤讀寫,訪問內容供應方、數據庫和網絡,其他需要較長時間的任務。

技巧3:使用最新的Android SDK版本和API
保持應用的更新,使用Android平臺提供的最新內容。隨著Android平臺的發展,它也在逐步改善中。某些功能被移除,或者替換成更好的選項。其核心API中的漏洞已修復,整個API性能已得到提升。該平臺已引入裝載器之類的新API,幫助開發者編寫更為穩定和反應靈敏的應用。
Android 3.0應用支持硬件加速,你可以加以應用。應當理解的是,最佳的表現情況會隨著時間逐漸改變。睿智的開發者會更新平臺發布的最新內容和API。

技巧4:檢查Strict Mode
你可以使用稱為“StrictMode”的Android API來查找編程中的問題。StrictMode會幫助你識別應用是否正在耗費內存,也可以幫你檢查應用是否正在嘗試開展漫長的模塊化操作。
StrictMode類(注:即android.os.StrictMode)與Android 2.3同期發布。

技巧5:在發布之前停用或最小化調試和診斷
你在Android應用的開發中可能會將某些調試代碼構建其中。在應用發布之前確保這些功能被最小化或完全停用。
接下來,讓我們來討論如何用優秀的用戶界面設計原則讓你的應用加載速度更快。

技巧6:保持布局簡潔自然
簡潔自然的布局會加快加載速度。不要讓屏幕布局中充斥過多不必要的內容。花點時間開發用戶可以有效使用的簡潔用戶界面,不要將過多的功能性內容塞入單個屏幕中。這不僅對應用表現有幫助,而且會幫助用戶更有效地使用應用。
分割內容可以幫助劃分用戶界面功能性,同時不犧牲應用在各種不同設備上的靈活性。

技巧7:根據目標設備調整應用資源
根據特定的設備配置來調整資源,這樣它們就能夠有效地加載。在圖像資源方面,這個顯得尤為重要。如果你的應用中有大型的圖片資源需要加載,那么要做好調整。
另一個技巧是,當以許多種設備為目標時,保持應用包文件大小合適,只需要在其中包含應用運行所需的核心資源即可,然后讓用戶根據具體設備下載應用其他內容。

技巧8:使用Hierarchy Viewer工具
Hierarchy Viewer工具可以幫助你解除應用布局中的漏洞。它還提供了許多有價值的信息,比如每個View控制需要多長的時間。找到問題所屬領域,這樣解決問題會更加簡單。

技巧9:使用layoutopt工具
layoutopt工具是個簡單的命令行工具,可以幫助你識別不必要的控制和其他讓你布局資源崩潰的事項,提升其性能。它可以幫助你找到不必要的多余布局控制。較少和較淺布局可優化應用運行性能。
最后,在自認為應用達到最好狀況時,對其進行測試。

技巧10:使用Traceview和其他Android應用壓縮工具
Android SDK中有許多可以壓縮應用的工具。可能最流行的工具就是Traceview,這個圖像工具可以幫助你調試和找到應用的性能問題。

結語
目前有許多方法可以讓你的Android應用運行加速。有些涉及到使用某種具體的運算法則,其他依靠某些真正的調試和運行監管技術。Android平臺中有許多種免費的工具可以用來幫助跟蹤和調整應用中的表現問題。你已經知道了以上10種技巧,現在可以嘗試使用它們!

由于本人現在在一家專職做網游的公司,所以現在需要使用一些方法對現運營的網游代碼進行精簡和優化,那么就要使用到Android sdk中提供的一款很好的檢視工具—Android TraceView、下面先給出對此的解釋:然后講解實現的詳細步驟和需要特別注意的一點!

 

什么是TraceView?先看下百度出來的解釋吧:

Traceview是android平臺配備一個很好的性能分析的工具。它可以通過圖形化的方式讓我們了解我們要跟蹤的程序的性能,并且能具體到method。

  關于Traceview的使用

  首先,必須在程序當中加入代碼,以便生成trace文件,有了這個trace文件才可以將其轉化為圖形。

  要添加的代碼如下:

  Java代碼

  // start tracing to "/sdcard/yourActivityTrace.trace"

  Debug.startMethodTracing("yourActivityTrace");

    // ... // stop tracing Debug.stopMethodTracing();

   // start tracing to "/sdcard/yourActivityTrace.trace" Debug.startMethodTracing("yourActivityTrace");

   // ... // stop tracing Debug.stopMethodTracing();

  Google Dev Guide當中說可以在activity的onCreate()中添加Debug.startMethodTracing(), 而在onDestroy()中添加Debug.stopMethodTracing(),但是在實際的測試時發現這種方式其實并不好用,因為通常情況下我們的activity的onDestroy()是由系統決定何時調用的,因此可能等了很長時間都不會得到這個trace文件。因此決定在onStop()中來調用Debug.stopMethodTracing()。這樣當我們切換到其它activity或者點擊home鍵的時候onStop()就會被調用,我們也就可以得到完整的trace file。

  在運行程序之前,首先要保證我們的AVD是一個帶有SD card的AVD,這樣才能使trace文件保存到/sdcard/...當中。運行后可以任意做一些操作,然后點擊home鍵。這是通過DDMS file explore就可以看到/sdcard/目錄下有一個trace文件,現在把這個文件copy到電腦上指定的目錄,假設是C:/tracefile 目錄下。

  可以通過命令行來執行traceview,進入tools目錄后,執行

  traceview C:/tracefile/yourActivityTrace.trace

  之后就可以看到圖形了,接下來就是按照Google Dev Guide中的解釋去分析圖形就OK了。

 

 

下面來看如何實現以及需要注意的地方:

 

  實現的步驟分為三步:1.必須先在我們的模擬器中創建sdCard ;2.將我們的調試代碼嵌入工程;3.利用TraceView來觀察和分析代碼情況;

 

1.對于創建模擬器的sdCard這里寫出兩種方式:

第一種:我們在eclipse中創建avd的時候的時候 在選擇api下面有個 Sd Card 的選項,第一項填入創建sdcard的大小即可。

                                         

第二種:cmd 命令! 打開cmd 并且cd 到android sdk tool 路徑下;(或者在環境變量Path中將sdk tool路徑配置上,然后重新打開cmd)

使用 mksdcard -l mycard 1024M F:/mysdcard.img 創建了一個1G的sdcard;

使用 emulator -avd my_android -sdcard F:/mysdcard.img 激活sdcard!

最后在eclipse Preferences-->Android-->Launch加入 -sdcard F:/mysdcard.img (此步驟就是在第一種創建方式中添加sdcard的支持)

 

備注1:

     如果sdcard分配的空間太小,則程序追蹤文件就一直記錄到sd儲蓄卡容量慢為止,所以調試前,要為程序生成一個適當的SD存儲卡也較為重要,因為程序運行時間越長,這個追蹤文件也就越大。


備注2;

(如果第二種創建方式中的第二部激活出現 emulator: ERROR: the user data image is used by another emulator. aborting,請關閉模擬器,或者進入目錄: /Documents and Settings / 用戶 / .android /的AVD / *設備* / (比如我的目錄是:C:/Documents and Settings/Administrator/.android/avd/android2.0.avd)

 

然后刪去以.lock結尾的文件夾就行(我簡單解釋下為什么要刪除這些文件呢,其實.lock是加鎖,如果程序崩潰等原因導致無法清除這些以.lock結尾的文件夾,就會出現這個問題,也就是這個avd的鎖沒有被釋放,導致avd manager以為這個avd正在使用當中。))


 

 

2.將我們的調試代碼嵌入工程

 正如我們百度到的說明一樣,在程序運行的開端加上  Debug.startMethodTracing("yourActivityTrace");  然后在onPause()中調用Debug.stopMethodTracing(); 為什么要將結束寫在onPause()中而不寫在onStop(),那么如果你去看api的話,你會看到,Api中介紹onPause()會在你返回和點擊home按鍵后觸發,而onStop()一般是由系統來觸發,當該程序處于后臺的時候,而且當內存緊張的時候,可能會調用,但是可能永遠不會調用到!

備注:要記住當把調試代碼加入項目中以后不要立即運行項目,而是必須在AndroidMainfest.xml中定義一條"寫入SD卡的權限"那么添加權限的代碼如下:

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>

因為咱們的調試代碼會在SD卡中生成一個追蹤文件,也就是往SD卡中寫入了數據,所以需要聲明一條權限。這里必須注意哦!


[java:showcolumns] view plaincopy

·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150

<?xml version="1.0" encoding="utf-8"?>  

<manifest xmlns:android="http://schemas.android.com/apk/res/android"  

      package="com.himi"  

      android:versionCode="1"  

      android:versionName="1.0">  

    <application android:icon="@drawable/icon" android:label="@string/app_name">  

        <activity android:name=".MainActivity"  

                  android:label="@string/app_name">  

            <intent-filter>  

10                 <action android:name="android.intent.action.MAIN" />  

11                 <category android:name="android.intent.category.LAUNCHER" />  

12             </intent-filter>  

13         </activity>  

14     </application>  

15     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>  

16     <uses-sdk android:minSdkVersion="4" />  

17 </manifest>   

 

 


 

3.運行項目并且退出項目從而得到的追蹤文件,利用TraceView來進行分析代碼運行狀況:

打當正常運行了項目并且點擊返回或者home按鍵就會在 sdcard中生成一個.trace的文件。sdcard 目錄 在eclipse下,點擊:

windows-show view-other-android-File explorer 

                                    

右上角的兩個箭頭,第一個表示從模擬器sdcard導出文件,第二個表示從PC上導入文件到sdcard中、“—”代表刪除 .....

然后我們通過cmd來運行生成的追蹤文件  traceview C:/name      追蹤文件所在的路徑放在C盤,放在C盤以外別的盤的話我這里是無法正常打開traceview的不知道什么原因。   name 表示生成的.trace文件,cmd的時候不需要輸入“.trace”后綴 ;然后會出現TraceView的分析窗口;

cmd 命令! 打開cmd 并且cd 到android sdk tools 路徑下;(或者在環境變量Path中將sdk tool路徑配置上,然后重新打開cmd)】

 

注意1:如果出現一下圖片這種內存溢出的問題;

 

 

解決方法:到SDK 下的tools 下 找到  traceview.bat 文件,鼠標右鍵-編輯(或者記事本打開),最后一行替換成這樣:

 

call java -Xms128m -Xmx512m -Djava.ext.dirs=%javaextdirs% -jar %jarpath% %*

 

注意2:如果出現路徑不對的問題:

例如:我的 himi.trace 放在了C盤,那么我的cmd命令是:   traceview c:/himi   然后回車!

但是這里要小心,因為 /h 這樣可能被認為是轉義字符!!!為了避免可以盡可能不要使用h,n,r,t,等等成為名字的頭字母,當然還有一種就可以完全避免這種問題,例如還是我的C盤 himi.trace 文件,可以寫cmd命令的時候寫成: traceview c://himi   嘿嘿~要注意細節。 

 

下面是運行起來的TranceView:

 

 

 

最右上角表示運行程序總共用了多少時間,從traceview畫面中我們看到有各種顏色,每種顏色代表不同的函數和步驟,那么同一顏色的區域越大,就代表這個步驟運行時間越長,或者看到下面的統計表,明顯可以看出除了序列 0 1 是系統函數外,2. 3.函數 占用的時間比較長,那么序列4是個自定義的函數名為 “hot”這個占用了幾乎與主線程 主draw的時間一樣了,那么肯定有問題。當然其實這個方法是我故意寫的,就是為了來演示traceview。這個hot函數的代碼如下:

[java:showcolumns] view plaincopy

·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150

18 /** 

19  * @author Himi 

20  * @param canvas 

21  */  

22     public void hot(Canvas canvas) {  

23         for (int i = 1; i < 100; i++) {  

24             Bitmap bmp = BitmapFactory.decodeResource(getResources(),  

25                     R.drawable.icon);  

26             canvas.drawBitmap(bmp, i += 2, i += 2, paint);  

27         }  

28     }  

 

很明顯我在故意消耗內存和時間。

 

那么,在traceview的右半部統計字段中:

Exclusive: 同級函數本身運行的時間

Inclusive 就是說除統計函數本身運行的時間外再加上調用子函數所運行的時間

 

Name:列出的是所有的調用項,前面的數字是編號,展開可以看到有的有Parent 和Children子項,就是指被調用和調用。

Incl: inclusive時間占總時間的白分比

Excl: 執行占總時間的白分比。

Calls+Recur Calls/Total: 調用和重復調用的次數

Time/Call: 總的時間。(ms)


 

所以traceview是個非常好的程序監視工具,可以幫助找出程序運行緩慢時的函數,讓我們的代碼不斷完善和改進!

 

 

OK,其次說說,如何提高Android的效率,也就是如何來優化Android的性能:

1,http用gzip壓縮,設置連接超時時間和響應超時時間

http請求按照業務需求,分為是否可以緩存和不可緩存,那么在無網絡的環境中,仍然通過緩存的httpresponse瀏覽部分數據,實現離線閱讀。

2.listview 性能優化

1).復用convertView

在getItemView中,判斷convertView是否為空,如果不為空,可復用。如果couvertview中的view需要添加listerner,代碼一定要在if(convertView==null){}之外。

2).異步加載圖片

item中如果包含有webimage,那么最好異步加載

3).快速滑動時不顯示圖片

當快速滑動列表時(SCROLL_STATE_FLING),item中的圖片或獲取需要消耗資源的view,可以不顯示出來;而處于其他兩種狀態(SCROLL_STATE_IDLE 和SCROLL_STATE_TOUCH_SCROLL),則將那些view顯示出來

4).BaseAdapter避免內存溢出

如果BaseAdapter的實體類有屬性非常消耗內存,可以將保存到文件;為提高性能,可以進行緩存,并限制緩存大小。

3.使用線程池,分為核心線程池和普通線程池,下載圖片等耗時任務放置在普通線程池,避免耗時任務阻塞線程池后,導致所有異步任務都必須等待

4.異步任務,分為核心任務和普通任務,只有核心任務中出現的系統級錯誤才會報錯,異步任務的ui操作需要判斷原activity是否處于激活狀態

5.盡量避免static成員變量引用資源耗費過多的實例,比如Context

6.使用WeakReference代替強引用,弱引用可以讓您保持對對象的引用,同時允許GC在必要時釋放對象,回收內存。對于那些創建便宜但耗費大量內存的對象,即希望保持該對象,又要在應用程序需要時使用,同時希望GC必要時回收時,可以考慮使用弱引用。

7.超級大胖子Bitmap

及時的銷毀(Activity的onDestroy時將bitmap回收,在被UI組件使用后馬上進行回收會拋 RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap)

設置一定的采樣率(有開發者提供的圖片無需進行采樣,對于有用戶上傳或第三方的大小不可控圖片,可進行采樣減少圖片所占的內存),從服務端返回圖片,建議同時反饋圖片的size

巧妙的運用軟引用

drawable對應resid的資源,bitmap對應其他資源

任何類型的圖片,如果獲取不到(例如文件不存在,或者讀取文件時跑OutOfMemory異常),應該有對應的默認圖片(默認圖片放在在apk中,通過resid獲取);

8.保證Cursor 占用的內存被及時的釋放掉,而不是等待GC來處理。并且 Android明顯是傾向于編 程者手動的將Cursor close掉

9.線程也是造成內存泄露的一個重要的源頭。線程產生內存泄露的主要原因在于線程 生命周期的不可控

10.如果ImageView的圖片是來自網絡,進行異步加載

11.應用開發中自定義View的時候,交互部分,千萬不要寫成線程不斷刷新界面顯示,而是根據TouchListener事件主動觸發界面的更新

12.Drawable

ui組件需要用到的圖片是apk包自帶的,那么一律用setImageResource或者setBackgroundResource,而不要根據resourceid

注意:get(getResources(), R.drawable.btn_achievement_normal)該方法通過resid轉換為drawable,需要考慮回收的問題,如果drawable是對象私有對象,在對象銷毀前是肯定不會釋放內存的。

13.復用、回收Activity對象臨時的activity及時finish主界面設置為singleTask一般界面設置為singleTop

14.位置信息獲取用戶的地理位置信息時,在需要獲取數據的時候打開GPS,之后及時關閉掉

15.在onResume時設置該界面的電源管理,在onPause時取消設置



/Files/gaolei-xj/android如何提升性能.rar