性能優(yōu)化-繪制優(yōu)化

前言

卡頓場(chǎng)景可分為以下四類(lèi):

  1. UI繪制:繪制呜笑、刷新
  2. 應(yīng)用啟動(dòng):安裝啟動(dòng)、冷啟動(dòng)叫胁、熱啟動(dòng)
  3. 頁(yè)面跳轉(zhuǎn):頁(yè)面間切換驼鹅、前后臺(tái)切換
  4. 事件響應(yīng):按鍵、系統(tǒng)事件输钩、滑動(dòng)

這四種卡頓場(chǎng)景的根本原因又可以分為兩大類(lèi):

  1. 界面繪制:主要原因是繪制的層級(jí)深张足、頁(yè)面復(fù)雜、刷新不合理哼绑。
  2. 數(shù)據(jù)處理:導(dǎo)致這種卡頓場(chǎng)景的原因是數(shù)據(jù)處理量太大碉咆,一般分為三種情況:
  • 一是數(shù)據(jù)處理在UI線(xiàn)程(這種應(yīng)該避免)。
  • 二是數(shù)據(jù)處理占用CPU高茂浮,導(dǎo)致主線(xiàn)程拿不到時(shí)間片次和。
  • 三是內(nèi)存增加導(dǎo)致GC頻繁,從而引起卡頓幌羞。

Android系統(tǒng)顯示原理

Android的顯示過(guò)程可以簡(jiǎn)單概括為:Android應(yīng)用程序把經(jīng)過(guò)測(cè)量、布局熊痴、繪制后的surface緩存數(shù)據(jù)聂宾,通過(guò)SurfaceFlinger把數(shù)據(jù)渲染到屏幕上,通過(guò)Android的刷新機(jī)制來(lái)刷新數(shù)據(jù)巾陕。

繪制原理

應(yīng)用層

在Android的每個(gè)view繪制中又三個(gè)核心步驟:Mesasure纪他、Layout、Draw。通過(guò)Measure和Layout來(lái)確定當(dāng)前需要繪制的view所在的大小和位置混聊,通過(guò)繪制(Draw)到surface句喜。

Measure和Layout都是遞歸來(lái)獲取view的大小和位置,并且以深度作為優(yōu)先級(jí)植康,因此層級(jí)越深展懈,元素越多,耗時(shí)也就越長(zhǎng)冻记。

系統(tǒng)層

應(yīng)用層和系統(tǒng)層是兩個(gè)不同進(jìn)程来惧,在Android的顯示系統(tǒng),使用匿名共享內(nèi)存:SharedClient隅居,每個(gè)應(yīng)用和SurfaceFlinger之間都會(huì)創(chuàng)建一個(gè)SharedClient。在每個(gè)SharedClient中棉钧,最多可以創(chuàng)建31個(gè)ShardBufferStack,每個(gè)Surface都對(duì)應(yīng)一個(gè)ShardBufferStack乒融,也就是一個(gè)window。 一個(gè)SharedClient對(duì)應(yīng)一個(gè)Android應(yīng)用程序愧捕,意味著一個(gè)Android應(yīng)用程序最多可以包含31個(gè)窗口申钩。

顯示整體流程分為三個(gè)模塊:應(yīng)用層繪制到緩存區(qū),SurfaceFlinger把緩存區(qū)數(shù)據(jù)渲染到屏幕邮偎,由于是兩個(gè)不同的進(jìn)程义黎,所以使用Android的匿名共享內(nèi)存SharedClient緩存需要顯示的數(shù)據(jù)來(lái)達(dá)到目的。

知道繪制原理后泻云,那么繪制一個(gè)單元多長(zhǎng)時(shí)間才是合理的狐蜕?
——在理想情況下层释,60FPS(Frames Per Second 每秒傳遞的幀數(shù))就感覺(jué)不到卡,這意味著每個(gè)繪制時(shí)長(zhǎng)應(yīng)該在16ms以?xún)?nèi)贡羔。

Android系統(tǒng)每隔16ms發(fā)出VSYNC信號(hào)治力,觸發(fā)對(duì)UI進(jìn)行渲染。若每次都成功就能達(dá)到流暢畫(huà)面的60FPS晕讲。若某個(gè)操作耗時(shí)較久,系統(tǒng)在得到VSYNC信號(hào)時(shí)就無(wú)法正常渲染瓢省,這樣就會(huì)發(fā)生丟幀現(xiàn)象勤婚。

==卡頓的根本原因==

影響繪制的根本原因有以下兩方面:

  1. ==繪制任務(wù)太重==,繪制一幀內(nèi)容耗時(shí)太長(zhǎng)馒胆。
  2. ==主線(xiàn)程太忙==祝迂,導(dǎo)致VSync信號(hào)來(lái)時(shí)還沒(méi)有準(zhǔn)備好數(shù)據(jù)導(dǎo)致丟幀。

性能分析工具

性能問(wèn)題不容易復(fù)現(xiàn)当凡,在分析性能問(wèn)題時(shí)需要借助相應(yīng)的調(diào)試工具纠俭,比如查看Layout層次的Hierarchy View、Android系統(tǒng)自帶的 Profile GPU卡頓檢測(cè)工具和靜態(tài)代碼檢查工具Lint朴则,以及性能分析常用的TraceView和SysTrace等钓简。

卡頓檢測(cè)工具

Profile GPU Rendering是Android4.1系統(tǒng)開(kāi)始提供的開(kāi)發(fā)輔助工具,可在開(kāi)發(fā)者選項(xiàng)中打開(kāi)(華為手機(jī)是:GPU呈現(xiàn)模式分析按鈕)

特點(diǎn):

  • 是一個(gè)圖形檢測(cè)工具,實(shí)時(shí)反應(yīng)當(dāng)前繪制的耗時(shí)欧宜。
  • 提供一個(gè)標(biāo)準(zhǔn)耗時(shí)坐榆,高于標(biāo)準(zhǔn)耗時(shí),表示當(dāng)前一幀丟失冗茸。


    image.png

各種顏色含義


image.png

技巧:
在實(shí)際開(kāi)發(fā)中席镀,圖形不便做數(shù)據(jù)分析,可通過(guò):adb shell dumpsys gfxinfo com.##.##(包名)把具體的耗時(shí)輸出到日志中來(lái)分析夏漱。

對(duì)大部分應(yīng)用來(lái)說(shuō)丟失幾幀影響不大豪诲,只需保證大部分在警戒線(xiàn)下即可挂绰。通過(guò)Profile GPU Rendering發(fā)現(xiàn)有問(wèn)題對(duì)頁(yè)面后屎篱,可通過(guò)另一個(gè)工具Hierarchy Viewer來(lái)查看布局層次和每個(gè)view所花時(shí)間具體定位。

TraceView

TraceView是AndroidSDK自帶的工具,用來(lái)分析函數(shù)調(diào)用過(guò)程交播,可以分析到應(yīng)用具體每一個(gè)方法的執(zhí)行時(shí)間重虑。

  1. 使用方法

在使用TraceView分析問(wèn)題之前需要得到一個(gè)*.trace的文件,然后通過(guò)TraceView來(lái)分析秦士。trace文件的獲取方法有兩種:

  • 通過(guò)Android Studio的Android Device Monitor缺厉,單擊Start Method Profile按鈕開(kāi)始監(jiān)控,操作要監(jiān)控的界面隧土,完成后stop就會(huì)跳到TraceView視圖提针。
  • 代碼中加入調(diào)試語(yǔ)句保存trace文件:android.os.Debug類(lèi)中提供類(lèi)相應(yīng)的方法,調(diào)用代碼如下:
//在開(kāi)始監(jiān)控的地方,保存在"/sdcard/trace_name.trace"
Debug.startMethodTracing("trace_name");
//...
//stop trace
Debug.stopMethodTracing();
  1. TraceView 視圖說(shuō)明
    TraceView視圖分兩個(gè)部分曹傀,上半部分為時(shí)間片面板辐脖,下半部分為分析面板。
  • 時(shí)間片面板:X軸表示時(shí)間消耗卖毁,Y表示各個(gè)線(xiàn)程揖曾,每個(gè)線(xiàn)程中的不同方法用不同顏色表示,顏色越寬表示該方法占用CPU時(shí)間越長(zhǎng)亥啦。
  • 分析面板:主要關(guān)注Calls + Recur Calls/Total(該方法調(diào)用次數(shù)+遞歸次數(shù))和Cpu Time / Call(該方法耗時(shí))這兩個(gè)值炭剪,也就是關(guān)注調(diào)用次數(shù)多和耗時(shí)久的方法,然后優(yōu)化這些方法的邏輯翔脱。

SysTrace UI性能分析

Systrace是Android4.1以上版本提供的性能數(shù)據(jù)采樣和分析工具奴拦。功能包括跟蹤系統(tǒng)的I/O操作、內(nèi)核工作隊(duì)列届吁、CPU負(fù)載等错妖。能直觀查看CPU周期消耗的具體時(shí)間,用不同顏色來(lái)突出問(wèn)題嚴(yán)重性疚沐,并提供解決建議暂氯。

注意:由于Systrace從系統(tǒng)角度返回一些信息,并不能定位到具體耗時(shí)的方法亮蛔,要具體分析原因要借助TraceView

  1. Systrace 使用方法
  • 在DDMS上使用:
    (1)打開(kāi)Android Device Monitor痴施,連接手機(jī)準(zhǔn)備好需抓取界面;
    (2)單擊Systrace進(jìn)入抓取前的設(shè)置究流,選擇需跟蹤內(nèi)容辣吃;
    (3)手機(jī)操作需跟蹤過(guò)程;
    (4)到設(shè)定時(shí)間后芬探,生成Trace文件神得,使用Chrome打開(kāi)文件。
  • 使用命令行
cd android-sdk/platform-tools/systrace
python systrace.py --time=10 -o mytrace.html sched gfx view wm

具體命令查看官方文檔

  • 應(yīng)用中獲韧捣隆:在應(yīng)用中加入Trace跟蹤需要注意兩點(diǎn):

(1)Trace嵌套時(shí)哩簿,endSection()方法只會(huì)結(jié)束離它最近的一個(gè)beginSection()宵蕉。所以要保證endSection和beginSection調(diào)用次數(shù)匹配。

(2)Trace的begin和end必須在同一線(xiàn)程中執(zhí)行卡骂。

public void ProcessPeople{
  Trace.beginSection("ProcessPeople");
  try{
      Trace.beginSection("Process One");
      try{
          //code
      }finally{
          Trace.endSection(); //end Process One
      }
      Trace.beginSection("Process Two");
      try{
          //code
      }finally{
          Trace.endSection(); //end Process Two
      }
  }finally{
      Trace.endSection(); //end ProcessPeople
  }
}
  1. 分析Systrace報(bào)告

通過(guò)前面方法獲取到的trace.html文件国裳,需要用Chrome打開(kāi),其中和UI繪制關(guān)系緊密的是Alerts和Frame兩個(gè)數(shù)據(jù)全跨。

  • Alerts:標(biāo)記了性能有問(wèn)題的點(diǎn)缝左,可以看到問(wèn)題的詳細(xì)描述
  • Frame:每個(gè)應(yīng)用都有一行專(zhuān)門(mén)顯示frame,它將任何它認(rèn)為性能有問(wèn)題的東西都高亮警告并提升怎么優(yōu)化浓若。

布局優(yōu)化

布局是否合理主要影響的是頁(yè)面測(cè)量時(shí)間的多少渺杉,如果層級(jí)太深,每增加一層則會(huì)增加更多的頁(yè)面顯示時(shí)間挪钓。

常用布局優(yōu)化工具

1. Hierarchy View

Hierarchy View是Android SDK自帶的調(diào)試工具是越,用來(lái)檢查L(zhǎng)ayout嵌套及繪制時(shí)間,以可視化的布局角度獲取Layout布局設(shè)計(jì)和各種屬性信息碌上。

使用:在Android Studio中打開(kāi)Android Device Monitor菜單倚评,直接打開(kāi)Hierarchy View

  • 查看層級(jí)圖:在window窗口頁(yè),選擇需要查看的組件馏予,雙擊或單擊Load View Hierarchy按鈕即可天梧。
  • 查看某個(gè)view的耗時(shí):在快捷鍵工具欄單擊Obtain layout times for tree rooted at selected node。

一個(gè)應(yīng)用界面非常多霞丧,如果一個(gè)個(gè)用Hierarchy View分析效率低呢岗,可以用另一個(gè)工具Lint,用于檢查所有頁(yè)面的層級(jí)蛹尝,并把深度高于N的界面輸出后豫,然后在用Hierarchy View仔細(xì)分析

2. 布局層級(jí)檢查

Android Lint是ADT 16之后引入的代碼檢查工具突那,通過(guò)代碼靜態(tài)檢查挫酿,可以發(fā)現(xiàn)潛在的代碼問(wèn)題,并給出優(yōu)化建議愕难。

使用前可在File -> Setting -> Inspections -> Android Lint中配置掃描規(guī)則和缺陷級(jí)別饭豹。

在Android studio中啟動(dòng)Lint:從菜單欄選擇Analyze -> Inspect Code,進(jìn)去后選擇掃描范圍掃描务漩。

布局優(yōu)化方法

通過(guò)減少Layout層級(jí),減少測(cè)量它褪、繪制時(shí)間饵骨,提高復(fù)用性三方方面來(lái)優(yōu)化布局,茫打,優(yōu)化的目的是減少層級(jí)居触,讓布局扁平化妖混,以提高繪制的時(shí)間,提高布局的復(fù)用性轮洋。

1. 減少層級(jí)

減少層級(jí)的兩個(gè)常用方案:

  • 合理使用RelativeLayout和LinearLayout
  • 合理使用Merge

合理使用RelativeLayout和LinearLayout

RelativeLayout相對(duì)LinearLayout能夠減少布局層級(jí)制市,但也存在性能低的問(wèn)題,原因是RelativeLayout會(huì)對(duì)子view做兩次測(cè)量弊予,因?yàn)橐蕾?lài)關(guān)系可能和布局中view順序不同祥楣,在確定子view位置時(shí),需先給所有子view做一次排序汉柒。

布局原則:

  • 盡量使用RelativeLayout和LinearLayout
  • 在層級(jí)相同時(shí)误褪,使用LinearLayout
  • 如果用LinearLayout會(huì)使層級(jí)變多,則應(yīng)該用RelativeLayout碾褂。

合理使用Merge

Merge是合并的意思兽间,可以有效優(yōu)化某些符合條件的多余層級(jí)。使用場(chǎng)景如下:

  • 在自定義view中使用正塌,父元素盡量是FrameLayout或者LinearLayout嘀略。
  • 在Activity中整體布局,根元素需要是FrameLayout乓诽。

Merge使用要求:

  • Merge只能用在布局XML文件的根元素帜羊。
  • 使用Merge加載布局時(shí),必須指定一個(gè)ViewGroup作為其父元素问裕,并且設(shè)置加載的attachToRoot參數(shù)為true逮壁。
  • 不能在ViewStub中使用Merge元素。(原因是ViewStub的inflate方法中根本沒(méi)有attachToRoot的設(shè)置)
2. 提高顯示速度

有時(shí)需要某個(gè)布局在一開(kāi)始不顯示粮宛,在某個(gè)條件下才顯示窥淆,可以通過(guò)visable屬性來(lái)控制,但這樣效率非常低巍杈,因?yàn)殡m然布局隱藏來(lái)忧饭,但還在布局中,仍會(huì)解析這些布局筷畦〈士悖可以使用ViewStub控件來(lái)解決這個(gè)場(chǎng)景并提高效率。

ViewStub是一個(gè)輕量級(jí)的View鳖宾,它是一個(gè)看不見(jiàn)的吼砂,并不占布局位置,占用資源非常小的視圖對(duì)象鼎文。

使用ViewStub注意的點(diǎn):

  • ViewStub只能加載一次渔肩,之后ViewStub對(duì)象會(huì)被置空。也就是布局被加載后就不能再用ViewStub來(lái)控制它的顯示隱藏拇惋。
  • ViewStub只能用來(lái)加載一個(gè)布局文件周偎,而不是某個(gè)具體的View抹剩。
  • ViewStub不能嵌套Merge標(biāo)簽。

ViewStub主要使用場(chǎng)景:

  • 在程序運(yùn)行期間蓉坎,某個(gè)布局被加載后澳眷,狀態(tài)就不會(huì)有變化。
  • 想要控制一個(gè)布局文件的隱藏/顯示蛉艾,而不是某個(gè)view
3. 布局復(fù)用

開(kāi)發(fā)過(guò)程中可以將一些公共的布局抽離出來(lái)作為一個(gè)布局文件钳踊,然后在需要使用的地方通過(guò)<include/>標(biāo)簽來(lái)實(shí)現(xiàn)引入。

對(duì)布局優(yōu)化的總結(jié)

  • 盡量使用RelativeLayout和LinearLayout
  • 盡可能少用wrap_content伺通,會(huì)增加布局Measure時(shí)的計(jì)算成本箍土,已知道寬高固定值時(shí)不用wrap_content。
  • 將復(fù)用組件抽取出來(lái)并通過(guò)<include/>標(biāo)簽使用
  • 使用<ViewStub/>標(biāo)簽加載按需顯示的布局
  • 使用<Merge/>標(biāo)簽減少布局嵌套層級(jí)
  • 刪除控件中無(wú)用屬性

避免過(guò)度繪制

過(guò)度繪制的主要原因

  • XML布局:控件有重疊且都有設(shè)置背景罐监。
  • View自繪:View.OnDraw里面同一個(gè)區(qū)域被繪制多次吴藻。

過(guò)度繪制檢測(cè)工具

通過(guò)手機(jī)設(shè)置中開(kāi)發(fā)者選項(xiàng),打開(kāi)Show GPU Overdraw選項(xiàng)(調(diào)試 GPU 過(guò)度繪制)弓柱,打開(kāi)后會(huì)有不同的顏色區(qū)域表示不同的過(guò)度繪制次數(shù)沟堡。不同顏色含義如下:

  • 無(wú)色:沒(méi)有過(guò)度繪制,每個(gè)像素只繪制來(lái)1次
  • 藍(lán)色:過(guò)度繪制 1 次(大片藍(lán)是可以接受的)
  • 綠色:過(guò)度繪制 2 次
  • 粉色:過(guò)度繪制 3 次(不要超過(guò)1/4)
  • 紅色:過(guò)度繪制 4 次或更多次(需優(yōu)化)

我們的目標(biāo)是減少紅色Overdraw矢空,看到更多藍(lán)色或無(wú)色區(qū)域航罗。

如何避免過(guò)度繪制

  1. 布局上的優(yōu)化
  • 移除XML中非必需的背景,或根據(jù)條件設(shè)置
  • 移除Window默認(rèn)背景
  • 按需顯示占位背景圖片

在Android自帶的一些主題時(shí)activity往往會(huì)設(shè)置一個(gè)默認(rèn)的背景屁药,這個(gè)背景有DecorView持有粥血。當(dāng)自定義布局有一個(gè)全屏背景時(shí),DecorView的背景此時(shí)對(duì)我們來(lái)說(shuō)是無(wú)用的酿箭,但會(huì)產(chǎn)生一次Overdraw复亏,因此可以移除

protect void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    this.getWindow().setBackgroundDrawaable(null);
}
  1. 自定義View優(yōu)化

自定義view能減少layout的層級(jí),但在實(shí)際繪制時(shí)容易出現(xiàn)過(guò)度繪制缭嫡〉抻可以通過(guò)canvas.clipRect()來(lái)幫組系統(tǒng)識(shí)別那些可見(jiàn)的區(qū)域,然后只在這個(gè)區(qū)域繪制妇蛀。canvas.quickreject()來(lái)判斷是否沒(méi)和某個(gè)矩形相交耕突,從而跳過(guò)那些非矩形區(qū)域內(nèi)的繪制操作。

啟動(dòng)優(yōu)化

應(yīng)用啟動(dòng)流程

啟動(dòng)分兩種類(lèi)型:冷啟動(dòng)和熱啟動(dòng)

  • 冷啟動(dòng):系統(tǒng)會(huì)重新創(chuàng)建一個(gè)新的進(jìn)程分配給它评架,所以會(huì)先創(chuàng)建和初始化Application類(lèi)眷茁,再創(chuàng)建和初始化Activity,最后顯示在界面纵诞。
  • 熱啟動(dòng):會(huì)從已有的進(jìn)程中啟動(dòng)上祈,所以熱啟動(dòng)不會(huì)再創(chuàng)建和初始化Application,而是直接創(chuàng)建和初始化Activity。

啟動(dòng) -> Application -> attachBaseContext() -> onCreate() -> Activity生命周期

啟動(dòng)耗時(shí)檢測(cè)

  1. adb shell am:使用adb shell獲取應(yīng)用真實(shí)啟動(dòng)時(shí)間代碼
adb shell am start -W [packageName]/[packageName.AppstartActivity]

執(zhí)行后得到三個(gè)時(shí)間

  • ThisTime:一般和TotalTime時(shí)間一樣雇逞,如果啟動(dòng)時(shí)加來(lái)過(guò)度全透明的頁(yè)面預(yù)先處理一些事,這樣會(huì)比TotalTime凶氯埂塘砸;
  • TotalTime:應(yīng)用啟動(dòng)時(shí)間,包括Application和Activity初始化到界面顯示晤锥;
  • WaitTime:包括系統(tǒng)影響的耗時(shí)掉蔬。

但這個(gè)方法只能得到固定某個(gè)階段耗時(shí),不能知道具體方法耗時(shí)矾瘾∨危可用代碼打點(diǎn)方式來(lái)得到具體方法耗時(shí)。

  1. 代碼打點(diǎn)

啟動(dòng)優(yōu)化方案

啟動(dòng)主要完成三件事:UI布局壕翩、繪制和數(shù)據(jù)準(zhǔn)備蛉迹,因此優(yōu)化啟動(dòng)速度也是優(yōu)化這三個(gè)過(guò)程。

  1. UI布局優(yōu)化
  • 減少布局層級(jí)
  • 避免過(guò)度繪制
  1. 啟動(dòng)加載邏輯優(yōu)化
    數(shù)據(jù)按需實(shí)現(xiàn)加載邏輯
  • 分步加載:以大化小放妈,優(yōu)先級(jí)高的放前
  • 異步加載:耗時(shí)多的異步化
  • 延期加載:非必需的數(shù)據(jù)延時(shí)加載

合理的刷新機(jī)制

合理的刷新機(jī)制要注意以下幾點(diǎn)北救;

  • 盡量減少刷新的次數(shù)
  • 盡量避免后臺(tái)有高CPU線(xiàn)程運(yùn)行
  • 縮小刷新區(qū)域

減少刷新次數(shù)

  1. 控制刷新頻率:比如刷新進(jìn)度調(diào)可1%刷新一次,而不是實(shí)時(shí)刷新
  2. 避免沒(méi)有必要的刷新:先判斷是否需要刷新芜抒,比如數(shù)據(jù)沒(méi)變化珍策、控件不在可見(jiàn)區(qū)域就沒(méi)必要刷新。

避免后臺(tái)線(xiàn)程影響

后臺(tái)線(xiàn)程如果開(kāi)銷(xiāo)很大宅倒,占用CPU過(guò)高攘宙,導(dǎo)致系統(tǒng)頻繁GC和CPU時(shí)間片資源緊張,有可能會(huì)導(dǎo)致頁(yè)面的卡頓拐迁。因此在需要迅速刷新的情況下避免這類(lèi)線(xiàn)程在高峰工作蹭劈。

縮小刷新區(qū)域

采用局部刷新來(lái)節(jié)約資源

  • 自定義view時(shí):可以使用兩個(gè)局部更新數(shù)據(jù)的方法
invalidate(Rect dirty)
invalidate(int left, int top, int right, int bottom)
  • 容器中的某個(gè)Item發(fā)生了變化,只需更新這個(gè)Item即可唠亚。

提升動(dòng)畫(huà)性能

從三個(gè)緯度來(lái)對(duì)比動(dòng)畫(huà)性能

  • 流暢度:核心链方,控制每一幀動(dòng)畫(huà)在16ms以?xún)?nèi)完成
  • 內(nèi)存:避免內(nèi)存泄漏,減小內(nèi)存開(kāi)銷(xiāo)
  • 耗電:減小運(yùn)算量灶搜,優(yōu)化算法祟蚀,減小CPU占用

優(yōu)化建議

  • 盡量使用屬性動(dòng)畫(huà)
  • 適當(dāng)使用硬件加速

使用硬件加速注意幾點(diǎn):

  • 在軟件渲染時(shí),可以使用重用Bitmap的方法來(lái)節(jié)省內(nèi)存割卖,但開(kāi)啟硬件加速后不起作用前酿。
  • 開(kāi)啟硬件加速的View在前臺(tái)運(yùn)行時(shí),需要耗費(fèi)額外的內(nèi)存鹏溯,加速的UI切換到后臺(tái)時(shí)罢维,產(chǎn)生的額外內(nèi)存有可能不釋放。
  • 當(dāng)UI中存在過(guò)度繪制時(shí)丙挽,硬件加速容易發(fā)生問(wèn)題肺孵。

參考書(shū)籍:《Android應(yīng)用性能優(yōu)化最佳實(shí)踐》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末匀借,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子平窘,更是在濱河造成了極大的恐慌吓肋,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瑰艘,死亡現(xiàn)場(chǎng)離奇詭異是鬼,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)紫新,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門(mén)均蜜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人芒率,你說(shuō)我怎么就攤上這事囤耳。” “怎么了敲董?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵紫皇,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我腋寨,道長(zhǎng)聪铺,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任萄窜,我火速辦了婚禮铃剔,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘查刻。我一直安慰自己键兜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布穗泵。 她就那樣靜靜地躺著普气,像睡著了一般。 火紅的嫁衣襯著肌膚如雪佃延。 梳的紋絲不亂的頭發(fā)上现诀,一...
    開(kāi)封第一講書(shū)人閱讀 49,185評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音履肃,去河邊找鬼仔沿。 笑死,一個(gè)胖子當(dāng)著我的面吹牛尺棋,可吹牛的內(nèi)容都是我干的封锉。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼成福!你這毒婦竟也來(lái)了碾局?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤奴艾,失蹤者是張志新(化名)和其女友劉穎擦俐,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體握侧,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年嘿期,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了品擎。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡备徐,死狀恐怖萄传,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蜜猾,我是刑警寧澤秀菱,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站蹭睡,受9級(jí)特大地震影響衍菱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜肩豁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一脊串、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧清钥,春花似錦琼锋、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至篡悟,卻和暖如春谜叹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背恰力。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工叉谜, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人踩萎。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓停局,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子董栽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

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