[if !supportLists]1.?[endif]activity生命周期
oncreate-onstart-onresume-onpause-onstop-ondetyoy
[if !supportLists]2.?[endif]service生命周期
service啟動方式有兩種,已知是托管start service方式進行啟動,另已知是通過bindservice方式進行啟動,不同的啟動方式他們的生命周期是不一樣的。
A.通過start service方式啟動的service,生命周期是這樣的,start service-oncreate-onstartconmon-ondestroy這種方式啟動的話,需要注意以下幾個問題。1.當我們通過start service被調用以后,多次在調用start service oncreate方法指揮被調用一次,onstartconmon方法會被多次調用,當我們調用stop service的時候,ondestroy就會被調用,從而銷毀服務,2.當我們通過start service啟動時候,通過intent傳值,在onstartconmon方法中獲取值的時候,一定要先判斷intent是否為null,
B.通過bindservice方式進行綁定,這種方式綁定service,生命周期走法,bindservice,oncreate onbind unbind ondestroy ?bindservice這種方式進行啟動service的好處是更加便利activity中操作service,比如加入service中有幾個方法,a,b如果需要在activitie中調用,在需要在activity獲取serviceconncation對象,通過servbiceconnecation或獲取service中內部類的類對象,然后通過這個類對象就可以調用類中的方法,當然這個類需要繼承binder對象、
[if !supportLists]3.?[endif]activity的啟動過程
App啟動的過程有兩種情況,第一張是從桌面launcher點擊相應應用圖標,第二種是在activity中過調用startactivity 來啟動一個新的activity。我們創(chuàng)建一個新的項目,默認的根activity就會在上一個activity上面,而我們從桌面點擊應用圖標的時候,由于launcher本身也是一個應用,當我們點擊圖標的時候,系統(tǒng)就會調用startactivitySately 一般情況下,我們所啟動的acytivity的相關信息都會保持在intent中,比如action category等等。我們在安裝這個應用的時候,系統(tǒng)也會啟動一個pack manager service的管理服務,這個管理服務會對Androidmanifest.xml文件進行解析,從而得到一個應用程序中的線管信息,比如service activity,broadcast等等,然后獲得相關組件的信息,當我們點擊應用圖標的時候就會調用startactivitySately方法,而這個方法內部則是調用startactivity,兒start activity方法最終還是會調用start activity for result這個方法,而在start activityforresulu這個方法,因為startactvityforresult是有返回結果的,所以系統(tǒng)就直接給一個-1,就表示不要結果返回,erstartactivityforresult這個方法實際是通過instrunmentation類中的execstartactivity方法來啟動activity,instrumentation這個類主要作用就是監(jiān)控程序和系統(tǒng)之間的交互,而在這個execstartactivity方法中獲取activitymanagerservice的代理對象,通過這個代理對象進行啟動activity。啟動就會調用checkstartactivityResult方法,如果說沒有在配置清單中配置有這個組件,就會在這個方法中拋出異常,當然最會是調用的是,application。schedule launch activity來進行啟動activity,而這個方法中通過獲取的到一個activity client record對象,而這個activity client record對象通過含量的人來進行雄安錫的發(fā)送,系統(tǒng)內不會講一個activity組件使用activity client record對象來進行描述,而activity client record對象中保持有一個loaderapk對象,通過這個對象調用含量的人launch activity來啟動activity組件,而頁面的生命周期方法也就是在這個方法中進行調用的。
[if !supportLists]4.?[endif]broadcast注冊方式與區(qū)別
Broadcast廣播,注冊方式主要有兩種
第一種是靜態(tài)注冊,也可以成為常駐型廣播,這種廣播需要在Androidmanifest.xml中進行注冊,這種方式注冊的發(fā)廣播,不受頁面生命周期的影響,即使推出了頁面。也可以收到廣播,這種廣播一般用于監(jiān)聽系統(tǒng)的事件,如開機啟動,來電,去電,鎖屏,由于這種注冊的方式的廣播是常駐型掛鉤吧,所以會贊揚cpu的資源、
第二種是動態(tài)注冊,而動態(tài)注冊的話,是在代碼中注冊的,這種注冊方式也叫非常駐型廣播,受到生命周期的影響,推出頁面后,就不會在收到廣播,我們通常運行在更新UI方面,這種注冊方式優(yōu)先級較高,最后需要解綁,否則會內存泄露,=廣播是分為有序廣播和無需廣播。
[if !supportLists]5.?[endif]HTTP client與httpurlconnecation的區(qū)別
首先HTTP client和httpurlconnecation都支持https協(xié)議,都是以流的形式進行上傳或者下周數(shù)據,也可以說是以流的形式進行數(shù)據的傳世,還有ipv6以及連接池等功能,httpclient這個擁有非常多的apl,所有如果想要進行擴展的話,并且不破壞他的兼容性的話,很難進行擴展,也就是這個原因,Google在Android6.0的時候,直接棄用了HTTP client,而httpurlconnecation相對來說就是比較輕量級了,apl比較少,容易擴展,并且能夠滿足Android大部分的數(shù)據傳輸,比較經典的一個框架volley,在2.3版本以前都是使用httpclient,在2.3以后就使用了httpurlconnecation
[if !supportLists]6.?[endif]Java虛擬機和dalvik的區(qū)別
Java虛擬機:
[if !supportLists]A.?[endif]Java虛擬機基于棧,基于棧的機器必須使用指令來載入和操作棧上數(shù)據,所需指令更多很多
[if !supportLists]B.?[endif]Java虛擬機運行的是Java字節(jié)碼,Java類會被編譯成成一個或者多個字節(jié)碼。Class文件
Dalvik虛擬機
[if !supportLists]A.?[endif]Dalvik虛擬機是基于寄存器的
[if !supportLists]B.?[endif]Dalvik運行的是自定義的.dex字節(jié)碼格式,Java類被編譯成,class文件后,會通過一個dx工具講所有的,class文件專場一個,dex文件,然后dalvik虛擬機就會從其中讀取指令和數(shù)據
[if !supportLists]C.?[endif]常量池已被修改為只使用32位的索引,以簡化解釋器
[if !supportLists]D.?[endif]一個應用,一個虛擬器實力,一個進行(所有Android應用的現(xiàn)場都是對應一個Linux線程,都運行在自己的沙盒中,不同的應用在不同的進程中運行,每個Android dalvik應用陳旭都被賦予了一個獨立的linux PID)
[if !supportLists]7.?[endif]進行?;?/p>
當前業(yè)界的Android進行?;钍侄沃饕譃?,黑,白,灰三種,其大致的實現(xiàn)思路如下,
[if !supportLists]A.?[endif]黑色?;?,不同app進行,用廣播相互喚醒,包括利用系統(tǒng)提供的廣播進行喚醒
[if !supportLists]B.?[endif]白色?;?,啟動前臺service
[if !supportLists]C.?[endif]灰色?;?,利用系統(tǒng)漏洞啟動前臺service
黑色?;睿?/p>
所謂的黑色?;?,就是利用不同的app進程是使用廣播來進行相互喚醒,舉三個比較常見的場景,
場景1,開機,網絡切換,拍照,拍視頻的時候,利用系統(tǒng)產生的廣播喚醒service或app
場景2,接入第三方sdk也會喚醒相應的app進程,如微信sdk會喚醒微信,支付寶sdk會喚醒支付,由此去散發(fā)開去,就會直接出發(fā)了下面的場景3
場景3,加入你手機里裝了支付寶,淘寶,天貓,uc等阿里系的app.那么你打開任意一個阿里系app后,有可能就順便把其他阿里系的app給喚醒了,
白色?;睢?/p>
白色?;钍侄畏浅:唵?,就是調用系統(tǒng)api啟動一個前臺service進行,這樣在系統(tǒng)的通知欄生成一個notification,用來讓用戶知道有這樣一個app在運行著,哪怕當前的app退到了后臺,如下發(fā)的lbe和qq音樂這樣
灰色?;?/p>
灰色?;睿@樣?;钍謾C是應用范圍最廣泛,他是利用系統(tǒng)的漏洞來啟動一個前臺service進程,與普通的啟動方式區(qū)別在于,它不會在系統(tǒng)通知欄出出現(xiàn)一個notification,看起來就如同運行這一個后臺service進行一樣,這樣做帶來的好處就是,用戶無法察覺到你運行著一個前臺進程,但你的進程優(yōu)先級又高于普通后臺進行的,那么如何利用系統(tǒng)的漏洞呢大致實現(xiàn)思路如下代碼
思路一,api<18,啟動前臺service時直接傳入new notification,
思路二,api>=18同時啟動兩個id相同的前臺service,然后講后啟動的service做stop處理
熟悉Android系統(tǒng)的童鞋都知道,系統(tǒng)處于體驗和性能上的考慮,app在推到后臺時系統(tǒng)并不會真正的kill掉這個進程,而是將其緩存起來,打開的應用程序越多,后臺換乘的進行也越多,在系統(tǒng)內存不足的情況下,系統(tǒng)開始一句資深的一套進程回收機制來判斷要kill掉哪些進程,以騰出內存來共給需要的app,這套殺進程回收內存的機制就叫,low memory killer 他是基于Linux內核的oom killer 機制誕生
進程的重要性,劃分五級
前臺進程foreground process
可見進行visible process
服務進service process
后臺進程background process
空進程empty process
了解完low memory killer在科普下 oom_adj ,生命是oom_adj?它是Linux內核分配給每個系統(tǒng)進程的一個值,代表進程的優(yōu)先級,進程回收機制就是根據這個優(yōu)先級來覺得十分進行回收,對于oom_adj的作用,只需要記住一下幾點即可。1.進行的oom_adj越大,表示此進程優(yōu)先級越低,越容易被殺掉回收,越小,表示進程的優(yōu)先級越高,越不容易被殺掉回收,普通app進行的oom_adj=0系統(tǒng)的進程oom_adj才可能<0
有些手機就廠商把這些知名的app放入可自己的白名單中,保證了進行不死來提高用戶體驗,(如微信,qq默默都在小米的白名單中)。如果從白名單移除,他們終究還是個普通appp一樣躲避不了被殺的命運,為了經理避免被殺,還是老老實實的去做好優(yōu)化工作吧
所以,進程?;罡痉桨附K究還是回到了性能優(yōu)化上,進程永生不死終究是個徹頭徹尾的偽命題
[if !supportLists]8.?[endif]Context
Context是一個抽象基類,在翻譯為上下文,可以理解為環(huán)境,是提供一些程序的運行環(huán)境基礎信息,context下又兩個子類,contextwapper是上下文功能的封裝類,而contextimpl則是上下文功能的實現(xiàn)類,而contextwapper又又三個直接子類,contextthemewrapper。Service和application,其中,context'themewrapper 是一個呆主題的封裝類,只有activity需要主題,service不需要主題,context一共又三種類型,分別是application,activity和service,這三個類型雖然承擔這不同的作用,單塔恩都屬于context的已知,而他們具體context的功能則是又contextimpl類去實現(xiàn)的,因此在絕大多數(shù)場景下,activity,service和application這三種類型的context都是可以通用的,不過有幾種場景比較特殊,把比如啟動activity,還有彈出dialog,處于安全原因的開了,Android是不允許activity或者dialog憑空出現(xiàn)的,一個activity的啟動必須要簡歷在另一個acyivity基礎之上,也就是以此形式的返回棧,而dialog則把必須在一個activity上面彈出,因為在這種場景下,我們只能使用activity類型的context,否則將會出錯。
ge'ta'p'p'li'ca'ti'o'nContext和getApplication方法得到的對象都是同一個application對象,只是對象的類型不一樣。
Context數(shù)量=activity數(shù)量+service數(shù)量+1(1為application)
[if !supportLists]9.?[endif]理解activity view window三者關系
這個問題真的很不好回答,所以這里先來個算是比較恰當?shù)谋热缧稳菹滤麄兊年P系吧
Activity像一個工匠(控制單元)window像窗戶(承載模型),view像窗花,(顯示試圖)layoutinflayer像簡單,xml配置像窗花圖紙
[if !supportLists]A.?[endif]activity構造的時候會初始化一個window,準確的說是phonewindow
[if !supportLists]B.?[endif]這個phone window有一個viewroot 這個viweroot是一個view或者說是view group,是最初始的根視圖
[if !supportLists]C.?[endif]view root通過add view方法來一個個添加view,比如textview,button等
[if !supportLists]D.?[endif]這些view的事件監(jiān)聽,是由window manager service來接受消息,并且回調activity函數(shù),比如onclicklistener ,onkeyDown等
[if !supportLists]10.?[endif]四種launchmode及其使用場景
[if !supportLists]A.?[endif]隊列先進先出,棧先進后出
[if !supportLists]B.?[endif]對插入和刪除的操作的限定,棧是限定只能在表的一端進行插入和刪除的操作線性表,隊列是限定只能在表的一端進行插入和另一端進行刪除操作的線性表
[if !supportLists]C.?[endif]遍歷數(shù)據速度不同
Srandard模式
這個是默認模式,每次激活activity時都會創(chuàng)建一個新的activity實例,并放入任務棧最頂端,
singleTop模式
如果在任務的棧頂正好存在該activity的實例,就復用該實例(會調用實例的onNewintent())否則會創(chuàng)建一個新實例,使用場景如新聞類或者閱讀類app的內容頁
singleTask模式
如果過棧中已經有該activity實例,就會復用該實例(調用實例的onnewintent())復用時,會讓該實例回到棧頂,因此在他上面的實例將會被移出棧,如果棧中不存在該實例,將會創(chuàng)建一個新的實例放入棧頂。
singleInstance模式
在一個新棧中光劍該activity實例,并讓多個應用共享該棧中的activity實例,一旦該模式的activity已經存在某個棧中,任何應用在己合該activity時都會復用該棧中的實例,(調用onNewinent)其效果相當于多個應用共享一個應用,不管誰激活該activity都會進入同一個應用中,】
[if !supportLists]11.?[endif]View的繪制流程
自定義控件:
[if !supportLists]A.?[endif]組合控件,這個自定義控件不需要我們自己繪制,二十使用原生控件組合成的新控 件,如標題欄
[if !supportLists]B.?[endif]擊沉原有的控件,這種自定義控件提供原生控件方法外,還可以添加一些自己的方法,如制作圓角,原型圖片等
[if !supportLists]C.?[endif]完全自定義控件,這個view上所展現(xiàn)的內容全部都時我們自己繪制出來的,比如說制作水波紋進度條。
View的繪制流程;onmeasure-onlayout-ondraw
第一步onmeasure測量試圖大小,從頂層父view到子view遞歸調用measure方法,measure方法有調用onmeasure
第二步。Onlayout確定view位置,進行頁面布局,從頂層父view像子view的詆毀調用view.layout方法的過程,即父view根據上一步measure子view所得到的布局大小和布局參數(shù)講view放在合適的位置上。
第三步:ondraw繪制試圖,viewroot創(chuàng)建一個canvas對象,然后調用ondraw,6個步驟,1繪制試圖的北京,2保持畫布的試圖layer,3繪制view的內容,4繪制view子視圖,如果沒有就不用,5還原試圖layer,6繪制滾動條
[if !supportLists]12.?[endif]View view group事件分發(fā)
[if !supportLists]A.?[endif]Touch事件分發(fā)中只有倆哥哥主教,view group和view,view group包含,oninterceptTouchEvent,dispatch Touch Event,onTouchEvent,三個相關事件,view包含dispatchTouchevent,onTouchEvent兩個相關事件,其中viewgroup又繼承于view
[if !supportLists]B.?[endif]view group和view組成了一個樹狀結構,根節(jié)點為activity內部包含的一個viewgroup
[if !supportLists]C.?[endif]觸摸事件有action_down,action_move,action_up組成,其中一次完整的觸摸事件中,down和up都只有一個,move有若干個,可以為0個
[if !supportLists]D.?[endif]當activity接受到touch事件時,將遍歷子view進行down事件的分發(fā),view group的遍歷可以堪稱時遞歸的,分發(fā)的目的時為了找到正真洋蔥處理本次完整觸摸事件的view,這個view會在touchuEvent結果返回true
[if !supportLists]E.?[endif]當某個子view返回true時,會中止down事件的分發(fā),同時view group中記錄該子view,接下來的move和up事件將又該子view直接進行處理,由與子view時保持在view group中的,多層view group的階段結構時,上級view group保持的會時真是處理事件的view所在的view group對象,如view group0-view group1-text view的結構,text view返回了true,它講被保持在view group中,而view groupc。。。
[if !supportLists]13.?[endif]保持activity狀態(tài)
onsaveInstanceState會在activitiy轉入后臺狀態(tài)之前調用,也就是onstop方法之間 ,onpause方法被調用后。
[if !supportLists]14.?[endif]Android中幾種動畫
幀動畫,指通過指定每一幀的圖片和播放時間,有序的進行播放而形成動畫效果,
補間動畫,指通過指定view的初始狀態(tài),變化時間,方式,通過一系列算法進行圖像變換,從而形成動畫效果,主要有alpha,scale,tranlate,rotate,四種效果,注意,只是在試圖層實現(xiàn)了動畫效果,并沒有真正改變view的屬性,
屬性動畫,Android3.0的時候才支持,通過不斷的改變view的屬性,不斷的重回而形成動畫效果,相比于試圖動畫,view的屬性時正在改變了,比如view的旋轉,放大,縮小
[if !supportLists]15.?[endif]Android中跨進程通訊的幾種方式
Android跨進程通訊,像intent,content provider,service,都可以跨進程通信,
Intent這款跨進程方式并不是訪問內存的形式,它需要傳入一個uri,比如打電話
content provider這種形式,是使用數(shù)據共享的形式進行數(shù)據共享
Service遠程服務 aidl
廣播
[if !supportLists]16.?[endif]aidl理解
Aidl。沒一個進程都有自己的dalvik vm實例,都有自己的一塊獨立的內存,都在自己的內存上存儲自己的數(shù)據,執(zhí)行者自己的操作,都在自己的那片狹小的控件里過完自己的一生,而aidl就類似與兩個進程之間的橋梁,使的兩個進程之間可以進行數(shù)據的傳遞,跨進程通信有多種選擇,比如broadcast receiver,messenger等,但是broadcast receiver占用系統(tǒng)資源比較多,如果事平凡的跨進程通信的話顯然事不可取的,messenger進行跨進程通信時請求隊列時同步進行的,無法并發(fā)執(zhí)行。
Binder機制簡單理解
在Android系統(tǒng)的binder機制中,是有client,service,servicemanager,binder,驅動程序組成的,其中,client,service,servicemanager 運行在用戶空間,binder驅動程序是運行在內核空間的,而binder就是把這四種組件粘合在一塊的粘合劑,其中核心的組件就是binder驅動程序,serve manage提供輔助管理的功能,而client和service正式binder驅動程序和service manager提供的基礎設施上實現(xiàn)c/s之間的通信,其中binder驅動程序提供設備文件.dev.binder與用戶空間進行交互
Client,service,servicemanager 通過open和ioctl文件操作相應的方法與binder驅動程序進行通信,而client和service之間的通信時通過binder驅動程序簡介實現(xiàn)的,而binder manager時一個守護進程,用來管理service 并像client提供查詢service接口的能力。
[if !supportLists]17.?[endif]Handler的原理
Android中主線程時不能進行好事操作的,子線程時不能進行更新ui的,所以就有了handler,它的作用就是實現(xiàn)現(xiàn)場之間的通信。
Handler整個流程中,主要有四個對象,handler message,message queue,looper,當應用創(chuàng)建的時候,就會在主線程中創(chuàng)建handler對象
我們通過要傳送的消息保持到message中,handler通過調用sendmessage方法講message發(fā)送到message queue中,看ii烹飪對象就會不斷的調用loop方法,不斷從message queue中取出message交給handler進行處理,從而實現(xiàn)線程之間的通信。
[if !supportLists]18.?[endif]Binder機制原理
在Android系統(tǒng)的binder機子中,時有client,service,servicemanager binder驅動程序組成的,其中client,service,servicemanager 運行在用戶空間,binder驅動程序時運行在內核空間的,而binder就是把這四種組件粘合在一塊的粘合劑,其中核心的組件就是binder驅動程序,servicemanager提供輔助管理的功能,而client和service正式在binder驅動程序和service manager提供的基礎設施上實現(xiàn)C/S之間的通信,其中binder驅動程序提供設備文件/dev/dinger與用戶控件進行交互,client,service,service manager通過open和ioctl文件操作相應的方法與binder驅動程序進行通信,而client和service之間的進程通信時通過binder驅動程序簡介實現(xiàn)的,而binder manager時一個守護線程,用來管理service,并像client提供查詢service接口的能力
[if !supportLists]19.?[endif]熱修復原理
我們知道Java虛擬機--jvm時價值類的class文件的,額Android虛擬機--dalvik/art/vm時價值類的dex文件的。
而他們價值類的時候都需要classloader,classloader有一個子類basedexcassLoader,而baseD'e'xClassLoader下有一個數(shù)據---DexPathList,用來存放dex文件,當baseDexClassLoader提供調用findclass方法時,實際上就是遍歷數(shù)據,找到相應的dex文件,找到,則直接講它return,而熱修復的解決方法就是講新dex添加到己合中,并且時在舊的dex的前臺,所以就會有限被去除且return返回
[if !supportLists]20.?[endif]Android內存泄露及管理
[if !supportLists]A.?[endif]內存溢出oom和內存泄漏(對象無法被回收)的區(qū)別
[if !supportLists]B.?[endif]引起內存泄漏的原因
[if !supportLists]C.?[endif]內存泄漏檢測工具leakcanary
內存溢出out of memory是指程序在申請內存時,沒有足夠的內存控件供其使用,出現(xiàn)out of memory。比如申請了一個integer,但給它存了long才能存下的數(shù),那就是內存溢出了,內存溢出通俗的講就是內存不夠用
內存泄漏memory leak。是指程序在申請內存后,無法釋放已申請的內存空間,一次內存泄漏危害可以忽略,但內存泄漏堆積后果很嚴重,無論多少內存,遲早會被占光
內存泄漏原因
Handler引起的內存泄漏
解決講handler什么為靜態(tài)內部類,就不會持有外部類second activity的引用,其生命周期就和外部類無關了。
單例模式引起的內存泄漏
解決context是applicationContext,由于applicationContext生命周期是和app一致的,不會導致內存泄漏
非靜態(tài)內部類創(chuàng)建靜態(tài)實例引起的內存泄漏
解決,把內部類修改為靜態(tài)的就可以避免內存泄漏了
非靜態(tài)匿名內部引起的內存泄漏
解決,講匿名內部類設置為靜態(tài)的
5注冊/反注冊未成對使用引起的內存泄漏
解決注冊廣播,eventbus等 記得解綁
資源對象沒有關閉引起的內存泄漏
在這些資源不適應的時候,記得調用相應的close destroy recycler release等方法釋放
己合對象沒有及時清理引起的內存泄漏
通常會把一些對象裝入己合中,當不使用的時候一定要記得即使清理己合,讓相關對象不在被引用
[if !supportLists]21.?[endif]Fragment與 Fragment與activity通信的方式
[if !supportLists]A.?[endif]直接在fragment中調用另外一個fragment中的方法
[if !supportLists]B.?[endif]使用接口回調
[if !supportLists]C.?[endif]使用廣播
[if !supportLists]D.?[endif]Fragment直接調用activity中的public方法
[if !supportLists]22.?[endif]AndroidUI適配
字體使用sp使用dp,多使用match_parent,wrap_context.weight
圖片資源,不同圖片的分辨率,放在相應文件夾下可以使用百分比替代
[if !supportLists]23.?[endif]App優(yōu)化
App優(yōu)化(工具 hierarchy viewer 分析布局工具 trace view測試分析耗時情況)
App啟動優(yōu)化
布局優(yōu)化
相應優(yōu)化
內存優(yōu)化
電池優(yōu)化
網絡優(yōu)化
App啟動優(yōu)化(針對冷啟動)
App啟動方式有三種
冷啟動:app沒有啟動或app進程被killed,系統(tǒng)中不存在該app進程,此時啟動app幾位冷啟動
熱啟動,熱啟動意味著你的app進程只是處于后臺,系統(tǒng)只是將其從后臺帶到前臺,棧是給用戶,介于冷啟動和熱啟動之間,一般來說在一下兩種情況下發(fā)生
[if !supportLists]1.?[endif]用戶back退出了app,然后又啟動,app進程可能還在運行,但是activity需要重建
[if !supportLists]2.?[endif]用戶退出app后,系統(tǒng)可能由于內存原因講app殺死,進程和activity都需要重啟,但是可以在oncreate中講北大殺死鎖保存的狀態(tài)恢復、
優(yōu)化:
Application的oncreate(特別時第三方sdk初始化),首屏activity的渲染都不要進行耗時操作,如果又,放在子線程或者intenservice中
布局優(yōu)化:
經理不要過于復雜的嵌套,
響應優(yōu)化:
Android系統(tǒng)每個16ms會發(fā)出VSYNC信號重繪我們的界面activity
頁面卡頓的原因:
[if !supportLists]1.?[endif]過于復雜的布局
[if !supportLists]2.?[endif]UI線程的復雜運算
[if !supportLists]3.?[endif]頻繁的GC,導致頻繁的gc有兩個原因,1內存抖動,即大量的對象被創(chuàng)建又在短時間內馬上被釋放,2瞬間產生大量的對象會嚴重占中內存區(qū)域
電池使用優(yōu)化(batterystats bugreport)
[if !supportLists]1.?[endif]優(yōu)化網絡請求
[if !supportLists]2.?[endif]定位中使用GPS。記得及時關閉