Android性能優(yōu)化1

1.布局優(yōu)化
2.繪制優(yōu)化
3.響應(yīng)速度優(yōu)化和ANR日志分析

布局優(yōu)化

布局優(yōu)化思想就是,盡量減少布局文件的層級(jí),以便減少android繪制的工作量.

刪除無(wú)用的控件和層級(jí),如果在相同層級(jí)的情況下,盡量用LinearLayout.而不用RelativeLayout.一個(gè)View能展示出來(lái),需要依次經(jīng)過(guò)measure奴愉,layout和draw三個(gè)過(guò)程才最終將一個(gè)View繪制出來(lái),而兩者過(guò)程存在不同的差異

RelativeLayout
因?yàn)镽elativeLayout允許A轨蛤,B 2個(gè)子View但狭,橫向上B依賴A,縱向上A依賴B甲献。所以RelativeLayout在onMeasure測(cè)量子控件的時(shí)候,會(huì)對(duì)子View做兩次measure(需要橫向縱向分別進(jìn)行一次排序測(cè)量)

LinearLayout
LinearLayout會(huì)先判斷線性規(guī)則,然后執(zhí)行對(duì)應(yīng)方向上的測(cè)量

1.RelativeLayout會(huì)讓子View調(diào)用2次onMeasure颂翼,LinearLayout 在有weight時(shí)晃洒,也會(huì)調(diào)用子View2次onMeasure
2.RelativeLayout的子View如果高度和RelativeLayout不同,則會(huì)引發(fā)效率問(wèn)題朦乏,當(dāng)子View很復(fù)雜時(shí)球及,這個(gè)問(wèn)題會(huì)更加嚴(yán)重。如果可以呻疹,盡量使用padding代替margin吃引。
3.在不影響層級(jí)深度的情況下,使用LinearLayout和FrameLayout而不是RelativeLayout。Google給開發(fā)者默新建了個(gè)RelativeLayout,而自己卻在DecorView中用了個(gè)LinearLayout镊尺。因?yàn)镈ecorView的層級(jí)深度是已知而且固定的朦佩,上面一個(gè)標(biāo)題欄,下面一個(gè)內(nèi)容欄庐氮。采用RelativeLayout并不會(huì)降低層級(jí)深度语稠,所以此時(shí)在根節(jié)點(diǎn)上用LinearLayout是效率最高的。而之所以給開發(fā)者默認(rèn)新建了個(gè)RelativeLayout,是希望開發(fā)者能采用盡量少的View層級(jí)來(lái)表達(dá)布局以實(shí)現(xiàn)性能最優(yōu)弄砍,因?yàn)閺?fù)雜的View嵌套對(duì)性能的影響會(huì)更大一些仙畦。

使用<include>標(biāo)簽復(fù)用布局,include只支持android:layout_開頭的屬性
使用<merge>標(biāo)簽減少布局層級(jí)

<!-- 未使用merge -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

    ...
</LinearLayout>
不使用merge
<!-- 使用mrge -->
<merge xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

    ...
</merge>
使用merge

在布局根節(jié)點(diǎn)和上一級(jí)布局根節(jié)點(diǎn)相同的情況下,使用merge標(biāo)簽會(huì)減少布局層級(jí)

使用ViewStub

<ViewStub
        android:id="@+id/view_stub"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout="@layout/布局C" />

加載的兩種方式:

((ViewStub)findViewById(R.id.view_stub)).setVisibility(View.VISIBLE);
View view = ((ViewStub)findViewById(R.id.view_stub)).inflate();

當(dāng)ViewStub被加載完成之后,就會(huì)被內(nèi)部的布局替換掉,這個(gè)時(shí)候ViewStub就不是布局的一部分了ViewStub不支持merge標(biāo)簽

繪制優(yōu)化

繪制優(yōu)化即是在View的onDraw方法要避免大量的操作.

不要在onDraw里面創(chuàng)建對(duì)象,因?yàn)閛nDraw可能會(huì)被頻繁調(diào)用,導(dǎo)致產(chǎn)生大量的臨時(shí)對(duì)象,占用過(guò)多的內(nèi)存,也會(huì)導(dǎo)致系統(tǒng)更加頻繁的gc ,降低程序的執(zhí)行效率
不要做耗時(shí)的任務(wù),不要執(zhí)行成千上萬(wàn)的循環(huán)操作,大量的循環(huán)會(huì)搶占CPU的時(shí)間片,導(dǎo)致view的繪制過(guò)程不順暢

響應(yīng)速度優(yōu)化和ANR日志分析

響應(yīng)速度優(yōu)化的思想是避免在主線程做耗時(shí)操作,響應(yīng)速度慢,一般體現(xiàn)在Activity的啟動(dòng)速度上,如果主線程做太多事情,會(huì)導(dǎo)致Activity啟動(dòng)時(shí)出現(xiàn)黑屏現(xiàn)象,甚至出現(xiàn)ANR.
android規(guī)定,Activity如果5秒無(wú)法響應(yīng)屏幕觸摸事件,或者鍵盤輸入事件,就會(huì)出現(xiàn)ANR,BroadcastReceiver如果10秒還未執(zhí)行完操作也會(huì)出現(xiàn)ANR

當(dāng)出現(xiàn)ANR,系統(tǒng)會(huì)在/data/anr/目錄下創(chuàng)建一個(gè)文件traces.txt
adb pull traces.txt導(dǎo)出文件,查看ANR的原因

模擬ANR 主線程耗時(shí)操作

在onCreate方法中耗時(shí)操作.
setContentView(R.layout.activity_test_anr);
        findViewById(R.id.anr_test).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SystemClock.sleep(30000);
            }
        });

然后導(dǎo)出traces.txt文件,并且找到本應(yīng)用的信息

----- pid 28803 at 2017-10-09 17:17:12 -----
Cmd line: 這里是應(yīng)用的包名

JNI: CheckJNI is off; workarounds are off; pins=0; globals=271

DALVIK THREADS:
(mutexes: tll=0 tsl=0 tscl=0 ghl=0)

"main" prio=5 tid=1 TIMED_WAIT
  | group="main" sCount=1 dsCount=0 obj=0x415baca8 self=0x414f3580
  | sysTid=28803 nice=0 sched=0/0 cgrp=apps handle=1074295124
  | state=S schedstat=( 0 0 0 ) utm=31 stm=31 core=6
  at java.lang.VMThread.sleep(Native Method)
  at java.lang.Thread.sleep(Thread.java:1013)
  at java.lang.Thread.sleep(Thread.java:995)
  at android.os.SystemClock.sleep(SystemClock.java:115)
  at 應(yīng)用包名.TestANRActivity$1.onClick(TestANRActivity.java:18)
  at android.view.View.performClick(View.java:4445)
  at android.view.View$PerformClick.run(View.java:18429)
  at android.os.Handler.handleCallback(Handler.java:733)
  at android.os.Handler.dispatchMessage(Handler.java:95)
  at android.os.Looper.loop(Looper.java:136)
  at android.app.ActivityThread.main(ActivityThread.java:5001)
  at java.lang.reflect.Method.invokeNative(Native Method)
  at java.lang.reflect.Method.invoke(Method.java:515)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:736)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:570)
  at dalvik.system.NativeStart.main(Native Method)

可以看到是在應(yīng)用包名.TestANRActivity$1.onClick然后調(diào)用了SystemClock.sleep方法導(dǎo)致的ANR.

模擬ANR同步鎖,等待

findViewById(R.id.anr_test).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        testANR();
                    }
                }).start();

                SystemClock.sleep(10);//延遲10毫秒,確保先執(zhí)行子線程獲得鎖
                init();
            }
        });
    }
    private synchronized void testANR() {
        SystemClock.sleep(30*10000);
    }
    private synchronized void init() {

    }

先讓testANR()方法獲取到鎖,然后init()方法再去獲取相同的鎖,但是鎖被testANR()同步住了,導(dǎo)致子線程和主線程搶占同步鎖,發(fā)生ANR

----- pid 24899 at 2017-10-09 17:35:10 -----
Cmd line:應(yīng)用包名

JNI: CheckJNI is off; workarounds are off; pins=0; globals=271

DALVIK THREADS:
(mutexes: tll=0 tsl=0 tscl=0 ghl=0)

"main" prio=5 tid=1 MONITOR
  | group="main" sCount=1 dsCount=0 obj=0x415baca8 self=0x414f3580
  | sysTid=24899 nice=0 sched=0/0 cgrp=apps handle=1074295124
  | state=S schedstat=( 0 0 0 ) utm=32 stm=25 core=2
  at 應(yīng)用包名.TestANRActivity.init(TestANRActivity.java:~0)
  - waiting to lock <0x41733870> (a 應(yīng)用包名.TestANRActivity) held by tid=15 (Thread-203)
  at 應(yīng)用包名.TestANRActivity.access$100(TestANRActivity.java:8)
  at 應(yīng)用包名.TestANRActivity$1.onClick(TestANRActivity.java:25)
  at android.view.View.performClick(View.java:4445)
  at android.view.View$PerformClick.run(View.java:18429)
  at android.os.Handler.handleCallback(Handler.java:733)
  at android.os.Handler.dispatchMessage(Handler.java:95)
  at android.os.Looper.loop(Looper.java:136)
  at android.app.ActivityThread.main(ActivityThread.java:5001)
  at java.lang.reflect.Method.invokeNative(Native Method)
  at java.lang.reflect.Method.invoke(Method.java:515)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:736)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:570)
  at dalvik.system.NativeStart.main(Native Method)

traces.txt日志分析,可以看到
at 應(yīng)用包名.TestANRActivity.init(TestANRActivity.java:~0)
waiting to lock <0x41733870> (a winbons.com.myapplication.TestANRActivity) held by tid=15 (Thread-203)

init等待鎖,這個(gè)鎖被tid=15 (Thread-203)持有了.

"Thread-203" prio=5 tid=15 TIMED_WAIT
  | group="main" sCount=1 dsCount=0 obj=0x41a9da90 self=0x6ba96b58
  | sysTid=25026 nice=0 sched=0/0 cgrp=apps handle=1805145208
  | state=S schedstat=( 0 0 0 ) utm=0 stm=0 core=5
  at java.lang.VMThread.sleep(Native Method)
  at java.lang.Thread.sleep(Thread.java:1013)
  at java.lang.Thread.sleep(Thread.java:995)
  at android.os.SystemClock.sleep(SystemClock.java:115)
  at 應(yīng)用包名.TestANRActivity.testANR(TestANRActivity.java:30)
  at 應(yīng)用包名.TestANRActivity.access$000(TestANRActivity.java:8)
  at 應(yīng)用包名.TestANRActivity$1$1.run(TestANRActivity.java:20)
  at java.lang.Thread.run(Thread.java:841)

可以看到tid=15 (Thread-203) 是一個(gè)子線程,正在 應(yīng)用包名.TestANRActivity.testANR中執(zhí)行SystemClock.sleep,導(dǎo)致的問(wèn)題.

平時(shí)出現(xiàn)ANR問(wèn)題,我們就可以通過(guò)traces.txt文件來(lái)分析具體的原因,定位以及解決問(wèn)題

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市音婶,隨后出現(xiàn)的幾起案子慨畸,更是在濱河造成了極大的恐慌,老刑警劉巖衣式,帶你破解...
    沈念sama閱讀 216,692評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件寸士,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡瞳收,警方通過(guò)查閱死者的電腦和手機(jī)碉京,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)螟深,“玉大人谐宙,你說(shuō)我怎么就攤上這事〗缁。” “怎么了凡蜻?”我有些...
    開封第一講書人閱讀 162,995評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)垢箕。 經(jīng)常有香客問(wèn)我划栓,道長(zhǎng),這世上最難降的妖魔是什么条获? 我笑而不...
    開封第一講書人閱讀 58,223評(píng)論 1 292
  • 正文 為了忘掉前任忠荞,我火速辦了婚禮,結(jié)果婚禮上帅掘,老公的妹妹穿的比我還像新娘委煤。我一直安慰自己,他們只是感情好修档,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評(píng)論 6 388
  • 文/花漫 我一把揭開白布碧绞。 她就那樣靜靜地躺著,像睡著了一般吱窝。 火紅的嫁衣襯著肌膚如雪讥邻。 梳的紋絲不亂的頭發(fā)上迫靖,一...
    開封第一講書人閱讀 51,208評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音兴使,去河邊找鬼系宜。 笑死,一個(gè)胖子當(dāng)著我的面吹牛鲫惶,可吹牛的內(nèi)容都是我干的蜈首。 我是一名探鬼主播,決...
    沈念sama閱讀 40,091評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼欠母,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼欢策!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起赏淌,我...
    開封第一講書人閱讀 38,929評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤踩寇,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后六水,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體俺孙,經(jīng)...
    沈念sama閱讀 45,346評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評(píng)論 2 333
  • 正文 我和宋清朗相戀三年掷贾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了睛榄。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,739評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡想帅,死狀恐怖场靴,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情港准,我是刑警寧澤旨剥,帶...
    沈念sama閱讀 35,437評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站浅缸,受9級(jí)特大地震影響轨帜,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜衩椒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評(píng)論 3 326
  • 文/蒙蒙 一蚌父、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧毛萌,春花似錦梢什、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)囤躁。三九已至冀痕,卻和暖如春荔睹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背言蛇。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工僻他, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人腊尚。 一個(gè)月前我還...
    沈念sama閱讀 47,760評(píng)論 2 369
  • 正文 我出身青樓吨拗,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親婿斥。 傳聞我的和親對(duì)象是個(gè)殘疾皇子劝篷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 前言 Android性能優(yōu)化對(duì)Android程序的維護(hù)和拓展是有很大幫助的,我們知道Android手機(jī)不管是內(nèi)存還...
    老實(shí)任閱讀 507評(píng)論 0 0
  • 太長(zhǎng)不看版:在 Android UI 布局過(guò)程中民宿,遵守一些慣用娇妓、有效的布局原則,可以制作出高效且復(fù)用性高的 UI活鹰。...
    Mupceet閱讀 3,841評(píng)論 0 14
  • 注意事項(xiàng): 布局優(yōu)化哈恰;盡量使用include、merge志群、ViewStub標(biāo)簽着绷,盡量不存在冗余嵌套及過(guò)于復(fù)雜布局(...
    HarryXR閱讀 5,166評(píng)論 1 19
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,082評(píng)論 25 707
  • 曾經(jīng),恐龍還是這個(gè)世界的霸主锌云。它們喜愛光和熱荠医,因此努力長(zhǎng)大,希望可以親吻太陽(yáng)宾抓。 它們的渴望愈加虔誠(chéng)子漩,于是翼龍出現(xiàn)...
    蒼默閱讀 119評(píng)論 0 0