久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Android客戶端性能優(yōu)化(魅族資深工程師毫無保留奉獻)

 WindySky 2016-03-01

標簽:

本文由魅族科技有限公司資深A(yù)ndroid開發(fā)工程師degao(嵌入式企鵝圈原創(chuàng)團隊成員)撰寫,,是degao在嵌入式企鵝圈發(fā)表的第一篇原創(chuàng)文章,,毫無保留地總結(jié)分享其在領(lǐng)導(dǎo)魅族多個項目開發(fā)中的Android客戶端性能優(yōu)化經(jīng)驗,極具實踐價值,!

即日起,,嵌入式企鵝圈將在之前五個專欄(Linux內(nèi)核驅(qū)動情景分析、資源緊缺型SOC嵌入式架構(gòu)設(shè)計,、嵌入式交叉工具鏈及其應(yīng)用,、嵌入式設(shè)計和編程、微信硬件平臺和物聯(lián)網(wǎng)解決方案)新增Android開發(fā)專欄,!更多Android,、Linux、嵌入式和物聯(lián)網(wǎng)原創(chuàng)技術(shù)分享敬請關(guān)注微信公眾號:嵌入式企鵝圈,。


眾所周知,,一個好的產(chǎn)品,除了功能強大,,好的性能也必不可少,。有調(diào)查顯示,近90%的受訪者會因為APP性能差而卸載,,性能也是造成APP用戶沮喪的頭號原因,。

那Android客戶端性能的指標都有哪些?如何發(fā)現(xiàn)和定位客戶端的性能問題,?本文結(jié)合多個項目的開發(fā)實踐,,給出了要關(guān)注的重要指標項目,以及定位和解決性能問題的一般步驟,。

性能優(yōu)化應(yīng)該貫穿于功能開發(fā)的全部周期,,而不是做完一次后面便不再關(guān)注。每次發(fā)布版本前,最好能對照標準檢查下性能是否達標,。

記?。寒a(chǎn)品=性能×功能!

一,、 性能檢查項

1. 啟動速度

1)這里的啟動速度指的是冷啟動的速度,,即殺掉應(yīng)用后重新啟動的速度,此項主要是和你的競品對比,。

2)不應(yīng)在Application以及Activity的生命周期回調(diào)中做任何費時操作,,具體指標大概是你在onCreate,onResume,,onStart等回調(diào)中所花費的總時間最好不要超過400ms,,否則用戶在桌面點擊你的應(yīng)用圖標后,將感覺到明顯的卡頓,。


2. 界面切換

1)應(yīng)用操作時,,界面和動畫不應(yīng)有明顯卡頓;

2)可通過在手機上打開 設(shè)置->開發(fā)者選項->調(diào)試GPU過度繪制,然后操作應(yīng)用查看gpu是否超線進行初步判斷,;

技術(shù)分享


3. 內(nèi)存泄露

1)back退出不應(yīng)存在內(nèi)存泄露,,簡單的檢查辦法是在退出應(yīng)用后,用命令`adb shell dumpsys meminfo 應(yīng)用包名`查看 `Activities Views` 是否為零;

2)多次進入退出后的占用內(nèi)存`TOTAL`不應(yīng)變化太大,;

技術(shù)分享

4.  onTrimMemory回調(diào)

1)應(yīng)用響應(yīng)此回調(diào)釋放非必須內(nèi)存,;

2驗證可通過命令`adb shelldumpsys gfxinfo 應(yīng)用包名-cmd trim 5`后,再)用命令`adb shell dumpsys meminfo 應(yīng)用包名`查看內(nèi)存大小


5. 過度繪制

1)打開設(shè)置中的GPU過度繪制開關(guān),,各界面過度繪制不應(yīng)超過2.5x,;也就是打開此調(diào)試開關(guān)后,,界面整體呈現(xiàn)淺色,,特別復(fù)雜的界面,紅色區(qū)域也不應(yīng)該超過全屏幕的四分之一,;


6. lint檢查:

1)通過Android Studio中的 Analyze->Inspect Code 對工程代碼做靜態(tài)掃描,;找出潛在的問題代碼并修改;

2) 0 error & 0warning,,如果確實不能解決,,需給出原因。

技術(shù)分享

7. 反射優(yōu)化:

1)在代碼中減少反射調(diào)用,;

2)對頻繁調(diào)用的返回值進行Cache,;


8.  穩(wěn)定性:

1)連續(xù)48小時monkey不應(yīng)出現(xiàn)閃退,anr問題,。

2)如果應(yīng)用接入了數(shù)據(jù)埋點的sdk,,比如百度統(tǒng)計sdk,,友盟統(tǒng)計sdk等,這些sdk都會將應(yīng)用的崩潰信息上報回來,,開發(fā)者應(yīng)每天關(guān)注這些統(tǒng)計到的崩潰日志,,嚴格控制應(yīng)用的崩潰率;


9.  耗電:

1)應(yīng)用進入后臺后不應(yīng)異常消耗電量,;

2)操作應(yīng)用后,,退出應(yīng)用,讓應(yīng)用處于后臺,,一段時間后通過`adb shell dumpsysbatterystats`查看電量消耗日志看是否存在異常,。

 

二、性能問題常見原因


性能問題一般歸結(jié)為三類:

1. UI卡頓和穩(wěn)定性:這類問題用戶可直接感知,,最為重要,;


2. 內(nèi)存問題:內(nèi)存問題主要表現(xiàn)為內(nèi)存泄露,或者內(nèi)存使用不當導(dǎo)致的內(nèi)存抖動,。如果存在內(nèi)存泄露,,應(yīng)用會不斷消耗內(nèi)存,易導(dǎo)致頻繁gc使系統(tǒng)出現(xiàn)卡頓,,或者出現(xiàn)OOM報錯,;內(nèi)存抖動也會導(dǎo)致UI卡頓,。


3. 耗電問題:會影響續(xù)航,,表現(xiàn)為不必要的自啟動,不恰當持鎖導(dǎo)致系統(tǒng)無法正常休眠,,系統(tǒng)休眠后頻繁喚醒系統(tǒng)等,;


三、UI卡頓常見原因和分析方法

下面分別介紹出現(xiàn)這些問題的常見原因以及分析這些問題的一般步驟,。

1.卡頓常見原因

1)人為在UI線程中做輕微耗時操作,,導(dǎo)致UI線程卡頓;

2) 布局Layout過于復(fù)雜,,無法在16ms內(nèi)完成渲染,;

3)同一時間動畫執(zhí)行的次數(shù)過多,導(dǎo)致CPU或GPU負載過重,;

4) View過度繪制,,導(dǎo)致某些像素在同一幀時間內(nèi)被繪制多次,從而使CPU或GPU負載過重,;

5) View頻繁的觸發(fā)measure,、layout,導(dǎo)致measure,、layout累計耗時過多及整個View頻繁的重新渲染,;

6) 內(nèi)存頻繁觸發(fā)GC過多(同一幀中頻繁創(chuàng)建內(nèi)存),,導(dǎo)致暫時阻塞渲染操作;

7) 冗余資源及邏輯等導(dǎo)致加載和執(zhí)行緩慢,;

8)工作線程優(yōu)先級未設(shè)置為Process.THREAD_PRIORITY_BACKGROUND,,導(dǎo)致后臺線程搶占UI線程cpu時間片,阻塞渲染操作,;

9) ANR,;


2. 卡頓分析解決的一般步驟:

1)解決過度繪制問題

>在設(shè)置->開發(fā)者選項->調(diào)試GPU過度繪制中打開調(diào)試,看對應(yīng)界面是否有過度繪制,,如果有先解決掉:

 技術(shù)分享

> 定位過渡繪制區(qū)域

> 利用Android提供的工具進行位置確認以及修改(HierarchyView , Tracer for OpenGL ES)

> 定位到具體的視圖(xml文件或者View)

> 通過代碼和xml文件分析過渡繪制的原因

> 結(jié)合具體情況進行優(yōu)化

> 使用Lint工具進一步優(yōu)化

 

2) 檢查是否有主線程做了耗時操作:

 嚴苛模式(StrictMode),,是Android提供的一種運行時檢測機制,用于檢測代碼運行時的一些不規(guī)范的操作,,最常見的場景是用于發(fā)現(xiàn)主線程的IO操作,。應(yīng)用程序可以利用StrictMode盡可能的發(fā)現(xiàn)一些編碼的疏漏。


> 開啟 StrictMode:

>> 對于應(yīng)用程序而言,,Android 提供了一個最佳使用實踐:盡可能早的在

android.app.Application 或 android.app.Activity 的生命周期使能 StrictMode,,onCreate()方法就是一個最佳的時機,越早開啟就能在更多的代碼執(zhí)行路徑上發(fā)現(xiàn)違規(guī)操作,。

>> 監(jiān)控代碼

 public voidonCreate() {

 if (DEVELOPER_MODE) {

 StrictMode.setThreadPolicy(newStrictMode.ThreadPolicy.Builder()

 .detectAll().penaltyLog() .build());

     StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()

 .detectAll().penaltyLog() .build());

 }

     super.onCreate();

}

如果主線程有網(wǎng)絡(luò)或磁盤讀寫等操作,,在logcat中會有"D/StrictMode"tag的日志輸出,從而定位到耗時操作的代碼,。

 

3)如果主線程無耗時操作,,還存在卡頓,有很大可能是必須在UI線程操作的一些邏輯有問題,,比如控件measure,、layout耗時過多等,此時可通過Traceview以及systrace來進行分析,。

4)Traceview:Traceview主要用做熱點分析,,找出最需要優(yōu)化的點。

> 打開DDMS然后選擇一個進程,,接著點擊上面的“Start Method Profiling”按鈕(紅色小點變?yōu)楹谏撮_始運行),,然后操作我們的卡頓UI,然后點擊"Stop Method Profiling",會打開如下界面:

技術(shù)分享

圖中展示了Trace期間各方法調(diào)用關(guān)系,調(diào)用次數(shù)以及耗時比例,。通過分析可以找出可疑的耗時函數(shù)并進行優(yōu)化,;


5)systrace:抓取trace:

> 執(zhí)行如下命令:

$ cd android-sdk/platform-tools/systrace

$ python systrace.py --time=10 -o mynewtrace.htmlsched gfx view wm

> 操作APP,然后會生成一個mynewtrace.html 文件,,用Chrome打開:

> 圖示如下:

技術(shù)分享

通過分析上面的圖,,可以找出明顯存在的layout,measure,,draw的超時問題,。


6)導(dǎo)入如下插件,,可通過在方法上添加@DebugLog來打印方法的耗時:

build.gradle:

buildscript {

       dependencies {

        //用于方便調(diào)試性能問題的打印插件。給訪法加上@DebugLog,,就能輸出該方法的調(diào)用參數(shù),,以及執(zhí)行時間;

       classpath ‘com.jakewharton.hugo:hugo-plugin:1.2.1‘

    }

}

//用于方便調(diào)試性能問題的打印插件,。給訪法加上@DebugLog,,就能輸出該方法的調(diào)用參數(shù),以及執(zhí)行時間,;

apply plugin: ‘com.jakewharton.hugo‘

java:

@DebugLog

public void test( int a ){

int b=a*a;

}

 

四,、內(nèi)存性能分析優(yōu)化

1.內(nèi)存泄露

該問題目前在項目中一般用leakcanary基本就能搞定,配置起來也相當簡單:

build.gradle:

dependencies {

   debugCompile‘com.squareup.leakcanary:leakcanary-android:1.3.1‘ // or 1.4-beta1

  releaseCompile ‘com.squareup.leakcanary:leakcanary-android-no-op:1.3.1‘// or 1.4-beta1

   testCompile‘com.squareup.leakcanary:leakcanary-android-no-op:1.3.1‘ // or 1.4-beta1

 }

java:

public class ExampleApplication extends Application {

 

  @Overridepublic void onCreate() {

   super.onCreate();

   LeakCanary.install(this);

  }

}

一旦有內(nèi)存泄露,,將會在通知欄生成一條通知,,點開可看到泄露的對象以及引用路徑:

技術(shù)分享

2.內(nèi)存抖動

如果代碼中存在在onDraw或者for循環(huán)等多次執(zhí)行的代碼中分配對象的行為,會導(dǎo)致運行過程中gc次數(shù)增多,,影響ui流暢度,。一般這些問題都可通過lint工具檢測出來。

 

五,、耗電量優(yōu)化建議

電量優(yōu)化主要是注意盡量不要影響手機進入休眠,,也就是正確申請和釋放WakeLock,另外就是不要頻繁喚醒手機,,主要就是正確使用Alarm,。


六、一些好的代碼實踐

1. 節(jié)制地使用Service

2. 當界面不可見時釋放內(nèi)存

3. 當內(nèi)存緊張時釋放內(nèi)存

4. 避免在Bitmap上浪費內(nèi)存

對大圖片,,先獲取圖片的大小信息,,根據(jù)實際需要展示大小計算inSampleSize,,最后decode,;

public static BitmapdecodeSampledBitmapFromFile(String filename,

int reqWidth, int reqHeight) {

// First decode with inJustDecodeBounds=true to checkdimensions

final BitmapFactory.Options options = newBitmapFactory.Options();

options.inJustDecodeBounds = true;

BitmapFactory.decodeFile(filename, options);

// Calculate inSampleSize

options.inSampleSize =

reqHeight);

calculateInSampleSize(options,

reqWidth,

// Decode bitmap with inSampleSize set

options.inJustDecodeBounds = false;

return BitmapFactory.decodeFile(filename, options);

}

public static intcalculateInSampleSize(BitmapFactory.Options options,

int reqWidth, int reqHeight) {

// Raw height and width of image

final int height = options.outHeight;

final int width = options.outWidth;

int inSampleSize = 1;

if (height > reqHeight || width > reqWidth) {

if (width > height) {

inSampleSize = Math.round((float) height / (float)reqHeight);

} else {

inSampleSize = Math.round((float) width / (float)reqWidth);

}

}

return inSampleSize;

}


5. 使用優(yōu)化過的數(shù)據(jù)集合

6. 謹慎使用抽象編程

7. 盡量避免使用依賴注入框架

很多依賴注入框架是基于反射的原理,雖然可以讓代碼看起來簡潔,,但是是有礙性能的,。

8. 謹慎使用externallibraries

9. 優(yōu)化整體性能

10. 使用ProGuard來剔除不需要的代碼

android {

    buildTypes {

        release{

           minifyEnabled true

           shrinkResources true

           proguardFiles getDefaultProguardFile(‘proguard-android.txt‘),‘src/main/proguard-project.txt‘

           signingConfig signingConfigs.debug

        }

}


11. 慎用異常,異常對性能不利

拋出異常首先要創(chuàng)建一個新的對象。Throwable 接口的構(gòu)造函數(shù)用名為

fillInStackTrace() 的本地方法,fillInStackTrace()方法檢查棧,收集調(diào)用跟蹤信

息,。只要有異常被拋出,VM 就必要調(diào)整調(diào)用棧,因為在處理過程中創(chuàng)建了一

個新對象,。

異常只能用于錯誤處理,不應(yīng)該用來控制程序流程。

以下例子不好:

try {

startActivity(intentA);

} catch () {

startActivity(intentB);

}

應(yīng)該用下面的語句判斷:

if (getPackageManager().resolveActivity(intentA, 0) !=null)

不要再循環(huán)中使用 try/catch 語句,應(yīng)把其放在最外層,,使用 System.arraycopy()代替 for 循環(huán)復(fù)制,。




Android客戶端性能優(yōu)化(魅族資深工程師毫無保留奉獻)

標簽:

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,謹防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多