Activity的啟動(dòng)流程
- 點(diǎn)擊桌面App圖標(biāo)银萍,Launcher進(jìn)程采用Binder IPC向system_server進(jìn)程發(fā)起startActivity請求屿笼;
- system_server進(jìn)程接收到請求后傀履,向zygote進(jìn)程發(fā)送創(chuàng)建進(jìn)程的請求捡多;
- Zygote進(jìn)程fork出新的子進(jìn)程撑帖,即App進(jìn)程;
- App進(jìn)程肿孵,通過Binder IPC向sytem_server進(jìn)程發(fā)起attachApplication請求唠粥;
- system_server進(jìn)程在收到請求后,進(jìn)行一系列準(zhǔn)備工作后停做,再通過binder IPC向App進(jìn) 程發(fā)送scheduleLaunchActivity請求晤愧;
- App進(jìn)程的binder線程(ApplicationThread)在收到請求后,通過handler向主線程發(fā)送LAUNCH_ACTIVITY消息雅宾;
- 主線程在收到Message后养涮,通過發(fā)射機(jī)制創(chuàng)建目標(biāo)Activity,并回調(diào)Activity.onCreate()等方法眉抬。
Activity四種啟動(dòng)模式
- 標(biāo)準(zhǔn)模式(默認(rèn)模式)android:launchMode="standard"
每次啟動(dòng)一個(gè)Activity就會(huì)創(chuàng)建一個(gè)新的實(shí)例贯吓。- 棧頂復(fù)用模式:android:launchMode="singleTop"
如果新Activity已經(jīng)位于任務(wù)棧的棧頂,就不會(huì)重新創(chuàng)建蜀变,并回調(diào)onNewIntent()方法悄谐。- 棧內(nèi)復(fù)用模式:android:launchMode="singleTask"
只要該Activity在一個(gè)任務(wù)棧中存在,都不會(huì)重新創(chuàng)建库北,并回調(diào)onNewIntent()方法- 單實(shí)例模式: android:launchMode="singleInstance"
具有此模式的Activity只能單獨(dú)位于一個(gè)任務(wù)棧中爬舰,且此任務(wù)棧中只有唯一一個(gè)實(shí)例们陆。
Android中有哪幾種類型的動(dòng)畫
- View動(dòng)畫(View Animation)/補(bǔ)間動(dòng)畫(Tween animation):對(duì)View進(jìn)行平移、縮放情屹、旋轉(zhuǎn)和透明度變化的動(dòng)畫坪仇,不能真正的改變view的位置。應(yīng)用如布局動(dòng)畫垃你、Activity切換動(dòng)畫
- 逐幀動(dòng)畫(Drawable Animation):是View動(dòng)畫的一種椅文,它會(huì)按照順序播放一組預(yù)先定義好的圖片
- 屬性動(dòng)畫(Property Animation):對(duì)該類對(duì)象進(jìn)行動(dòng)畫操作,真正改變了對(duì)象的屬性
談?wù)勏C(jī)制Hander
- 作用:跨線程通信惜颇。當(dāng)子線程中進(jìn)行耗時(shí)操作后需要更新UI時(shí)皆刺,通過Handler將有關(guān)UI的操作切換到主線程中執(zhí)行。
- Message(消息):需要被傳遞的消息凌摄,其中包含了消息ID羡蛾,消息處理對(duì)象以及處理的數(shù)據(jù)等,由MessageQueue統(tǒng)一列隊(duì)锨亏,最終由Handler處理痴怨。
- MessageQueue(消息隊(duì)列):用來存放Handler發(fā)送過來的消息,內(nèi)部通過單鏈表的數(shù)據(jù)結(jié)構(gòu)來維護(hù)消息列表屯伞,等待Looper的抽取腿箩。
- Handler(處理者):負(fù)責(zé)Message的發(fā)送及處理豪直。通過 Handler.sendMessage() 向消息池發(fā)送各種消息事件劣摇;通過 Handler.handleMessage() 處理相應(yīng)的消息事件。
- Looper(輪詢器):通過Looper.loop()不斷地從MessageQueue中抽取Message弓乙,按分發(fā)機(jī)制將消息分發(fā)給目標(biāo)處理者末融。
Handler導(dǎo)致的內(nèi)存泄漏
- 泄漏原因:Message持有對(duì)Handler的引用,而非靜態(tài)內(nèi)部類的Handler又隱式持有對(duì)外部類Activity的引用暇韧,使得引用關(guān)系會(huì)保持至消息得到處理勾习,從而阻止了Activity的回收。
- 防止泄漏:
1懈玻、當(dāng)外部類結(jié)束生命周期時(shí)清空消息隊(duì)列removeCallbacksAndMessages(null)
2巧婶、使用靜態(tài)內(nèi)部類+WeakReference弱引用
主線程中Looper的輪詢死循環(huán)為何沒有阻塞主線程
Android是依靠事件驅(qū)動(dòng)的,通過Loop.loop()不斷進(jìn)行消息循環(huán)涂乌,可以說Activity的生命周期都是運(yùn)行在 Looper.loop()的控制之下艺栈,一旦退出消息循環(huán),應(yīng)用也就退出了湾盒。而所謂的導(dǎo)致ANR多是因?yàn)槟硞€(gè)事件在主線程中處理時(shí)間太耗時(shí)湿右,因此只能說是對(duì)某個(gè)消息的處理阻塞了Looper.loop()
談?wù)剮讉€(gè)常用的框架的實(shí)現(xiàn)原理
Glide框架
Glide.with(content).load(url).into(imageView) ,with綁定生命周期罚勾,load指定加載資源毅人,into指明加載目標(biāo)吭狡。
with:創(chuàng)建一個(gè)無UI的Fragment,通過添加的這個(gè)Fragment 感知 Activity 丈莺、Fragment 的生命周期划煮,將RequestManager存入到之這個(gè)Fragment的LifeCycle,
通過Lifecycle在Fragment關(guān)鍵生命周期通知RequestManger進(jìn)行相關(guān)的操作缔俄。
緩存機(jī)制:
1般此、活動(dòng)緩存, 弱應(yīng)用 HashMap,如果當(dāng)前對(duì)應(yīng)的圖片資源正在使用牵现,則這個(gè)圖片會(huì)被Glide放入活動(dòng)緩存铐懊。
Map<Key, ResourceWeakReference> activeEngineResources = new HashMap<>();
2、內(nèi)存緩存, LruCache LinkedHasMap瞎疼,如果圖片最近被加載過科乎,并且當(dāng)前沒有使用這個(gè)圖片,則會(huì)被放入內(nèi)存中贼急。
Map<T, Y> cache = new LinkedHashMap<>(100, 0.75f, true);
3茅茂、磁盤緩存(DiskLruCache)緩存圖片到本地文件夾。
Retrofit框架
Retrofit通過動(dòng)態(tài)代理太抓,用MethodHandler完成接口方法空闲。
Retrofit的MethodHandler通過RequestFactoryParser.parse解析,獲得接口方法的參數(shù)和注解的值走敌,傳入到OkHttpCall碴倾,OkHttpCall生成okhttp3.Call完成Http請求并使用Converter解析數(shù)據(jù)回調(diào)。
Retrofit通過工廠設(shè)置CallAdapter和Converter掉丽,CallAdapter包裝轉(zhuǎn)換Call跌榔,Converter轉(zhuǎn)換(解析)服務(wù)器返回的數(shù)據(jù)、接口方法的注解參數(shù)捶障。
OkHttp 是一個(gè)高效的 HTTP 客戶端僧须,具有非常多的優(yōu)勢:
1、能夠高效的執(zhí)行 http项炼,數(shù)據(jù)加載速度更快担平,更省流量
2、支持 GZIP 壓縮锭部,提升速度暂论,節(jié)省流量
3、緩存響應(yīng)數(shù)據(jù)空免,避免了重復(fù)的網(wǎng)絡(luò)請求
4空另、使用簡單,支持同步阻塞調(diào)用和帶回調(diào)的異步調(diào)用
OkHttp流程:
1蹋砚、采用責(zé)任鏈方式的攔截器,實(shí)現(xiàn)分成處理網(wǎng)絡(luò)請求,可更好的擴(kuò)展自定義攔截器(采用GZIP壓縮扼菠,支持http緩存)
2摄杂、采用線程池(thread pool)和連接池(Socket pool)解決多并發(fā)問題,同時(shí)連接池支持多路復(fù)用(http2才支持,可以讓一個(gè)Socket同時(shí)發(fā)送多個(gè)網(wǎng)絡(luò)請求,內(nèi)部自動(dòng)維持順序.相比http只能一個(gè)一個(gè)發(fā)送,更能減少創(chuàng)建開銷))
3、底層采用socket和服務(wù)器進(jìn)行連接.采用okio實(shí)現(xiàn)高效的io流讀寫
分化器 dispatcher:內(nèi)部維護(hù)隊(duì)列與線程池循榆,完成請求調(diào)配析恢。
// 雙端隊(duì)列,支持首尾兩端 雙向開口可進(jìn)可出
// 準(zhǔn)備運(yùn)行的異步隊(duì)列
private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();
// 正在運(yùn)行的異步
private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();
// 正在執(zhí)行的同步隊(duì)列
private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();
攔截器:5個(gè)攔截器秧饮,完成整個(gè)請求過程
1映挂、BridgeInterceptor(橋接攔截器):請求時(shí),對(duì)必要的Header進(jìn)行一些添加盗尸,接收響應(yīng)時(shí)柑船,移除必要的Header
2、RetryAndFollowUpInterceptor(重試與重定向攔截器):負(fù)責(zé)失敗重試以及重定向
3泼各、CacheInterceptor(緩存攔截器):負(fù)責(zé)讀取緩存直接返回(根據(jù)請求的信息和緩存的響應(yīng)的信息來判斷是否存在緩存可用)鞍时、更新緩存
4、ConnectInterceptor(連接攔截器):負(fù)責(zé)和服務(wù)器建立連接
5扣蜻、CallServerInterceptor(請求服務(wù)器攔截器):完成HTTP協(xié)議報(bào)文的封裝和解析逆巍。
LeakCanary 原理
1、通過 registerActivityLifecycleCallbacks 監(jiān)聽Activity或者Fragment 銷毀時(shí)候的生命周期莽使。
在Application.ActivityLifecycleCallbacks 的 onActivityDestroyed方法調(diào)用RefWatcher.watch()實(shí)現(xiàn)锐极。
2、通過弱引用和引用隊(duì)列監(jiān)控對(duì)象是否被回收(弱引用和引用隊(duì)列ReferenceQueue聯(lián)合使用時(shí)芳肌,
如果弱引用持有的對(duì)象被垃圾回收灵再,Java虛擬機(jī)就會(huì)把這個(gè)弱引用加入到與之關(guān)聯(lián)的引用隊(duì)列中。
即 KeyedWeakReference持有的Activity對(duì)象如果被垃圾回收庇勃,該對(duì)象就會(huì)加入到引用隊(duì)列queue)檬嘀。
Android 創(chuàng)建多個(gè)進(jìn)程,Android中的進(jìn)程通信
通過在配置清單中給四大組件設(shè)置android:process屬性值槽驶,這樣我們就可以輕易開啟多進(jìn)程模式责嚷。
Android中支持的多進(jìn)程通信方式主要有以下幾種,它們之間各有優(yōu)缺點(diǎn)掂铐,可根據(jù)使用場景選擇選擇:
1罕拂、AIDL:功能強(qiáng)大,支持進(jìn)程間一對(duì)多的實(shí)時(shí)并發(fā)通信全陨,并可實(shí)現(xiàn) RPC (遠(yuǎn)程過程調(diào)用)爆班。
2、Messenger:支持一對(duì)多的串行實(shí)時(shí)通信辱姨, AIDL 的簡化版本柿菩。
3、Bundle:四大組件的進(jìn)程通信方式雨涛,只能傳輸 Bundle 支持的數(shù)據(jù)類型枢舶。
4懦胞、ContentProvider:強(qiáng)大的數(shù)據(jù)源訪問支持,主要支持 CRUD 操作凉泄,一對(duì)多的進(jìn)程間數(shù)據(jù)共享躏尉,例如我們的應(yīng)用訪問系統(tǒng)的通訊錄數(shù)據(jù)。
5后众、BroadcastReceiver:即廣播胀糜,但只能單向通信,接收者只能被動(dòng)的接收消息蒂誉。
6教藻、文件共享:在非高并發(fā)情況下共享簡單的數(shù)據(jù)。
7右锨、Socket:通過網(wǎng)絡(luò)傳輸數(shù)據(jù)怖竭。
談?wù)?MVC、MVP陡蝇、MVVM
- MVC:
模型層(Model) :針對(duì)業(yè)務(wù)模型痊臭,建立數(shù)據(jù)結(jié)構(gòu)和相關(guān)的類,它主要負(fù)責(zé)網(wǎng)絡(luò)請求登夫,數(shù)據(jù)庫處理广匙,I/O的操作。
視圖層(View) :對(duì)應(yīng)于xml布局文件和java代碼動(dòng)態(tài)view部分恼策。
控制層(Controller) :控制層是由Activity/Fragment來承擔(dān)的鸦致,但是因?yàn)閄ML視圖功能太弱,所以Activity/Fragment既要負(fù)責(zé)視圖的顯示又要加入控制邏輯涣楷,承擔(dān)的功能過多分唾,大項(xiàng)目就會(huì)遇到耦合過重,Activity/Fragment類過大等問題狮斗。- MVP:為了解決MVC耦合過重的問題绽乔,MVP的核心思想就是提供一個(gè)Presenter將視圖邏輯和業(yè)務(wù)邏輯相分離,達(dá)到解耦的目的碳褒。
但是隨著業(yè)務(wù)邏輯的增加折砸,一個(gè)頁面可能會(huì)非常復(fù)雜,UI的改變是非常多沙峻,會(huì)有非常多的case睦授,這樣就會(huì)造成View的接口會(huì)很龐大。- MVVM:使用ViewModel代替Presenter摔寨,實(shí)現(xiàn)數(shù)據(jù)與View的雙向綁定去枷,這樣就省去了很多在View層中寫很多case的情況,只需要改變數(shù)據(jù)就行。
RecycleView 四級(jí)緩存
- 一級(jí)緩存:兩個(gè) ArrayList删顶,一個(gè)存儲(chǔ)當(dāng)前還在屏幕中的 ViewHolder疗隶,另一個(gè)存儲(chǔ)數(shù)據(jù)被更新的 ViewHolder
final ArrayList<ViewHolder> mAttachedScrap = new ArrayList<>();
ArrayList<ViewHolder> mChangedScrap = null;- 二級(jí)緩存:ArrayList,默認(rèn)大小為2翼闹,通常用來存儲(chǔ)預(yù)取的 ViewHolder斑鼻,同時(shí)在回收 ViewHolder時(shí),也可能會(huì)存儲(chǔ)一部分的 ViewHolder
final ArrayList<ViewHolder> mCachedViews = new ArrayList<ViewHolder>();- 三級(jí)緩存:ViewCacheExtension猎荠,自定義緩存【是空實(shí)現(xiàn)坚弱,一般都不會(huì)去實(shí)現(xiàn)它】
- 四級(jí)緩存:RecycledViewPool,緩存從二級(jí)緩存中移除的 ViewHolder关摇。采用 SparseArray 保存其內(nèi)部靜態(tài)類 ScrapData荒叶,ScrapData 采用 ArrayList 存儲(chǔ) ViewHolder,ArrayList 大小默認(rèn)為5输虱,可動(dòng)態(tài)改變些楣。ViewHolder 從二級(jí)緩存移除,加入四級(jí)緩存前宪睹,會(huì)將數(shù)據(jù)全部清除愁茁,根據(jù) ViewType 存儲(chǔ)到 SparseArray 中。ViewHolder 服用時(shí)會(huì)重寫 onBindViewHolder 方法填充數(shù)據(jù)亭病。
AIDL簡單講解一下鹅很。底層實(shí)現(xiàn)的是什么機(jī)制?
AIDL是進(jìn)程間通信的一種方式罪帖,底層實(shí)現(xiàn)是通過Binder機(jī)制來實(shí)現(xiàn)的促煮。Binder機(jī)制底層又是通過mmap內(nèi)存映射原理來實(shí)現(xiàn)的,內(nèi)存分為用戶空間和內(nèi)核空間整袁,Binder機(jī)制通過一次一次的數(shù)據(jù)拷貝來傳遞數(shù)據(jù)菠齿。
Binder機(jī)制了解
每個(gè)進(jìn)程的內(nèi)存空間都分為用戶空間和內(nèi)核空間,用戶空間和內(nèi)核空間之間的通信需要native層的方法來實(shí)現(xiàn)坐昙,方法叫copy_form_user()绳匀。進(jìn)程A的內(nèi)核空間和進(jìn)程B的用戶空間通過Linux的一個(gè)mmap方法來創(chuàng)建出一個(gè)共享的物理內(nèi)存地址,然后進(jìn)程A的用戶空間和進(jìn)程B的用戶空間進(jìn)行通信的話民珍,就只需要進(jìn)程A的用戶空間往進(jìn)程A的內(nèi)核空間進(jìn)行一次數(shù)據(jù)拷貝(copy_from_user)襟士,進(jìn)程B的用戶空間與進(jìn)程A的內(nèi)核空間通過mmap內(nèi)存映射的方式,就能在共享的物理內(nèi)存中獲取到進(jìn)程A拷貝的數(shù)據(jù)嚷量,就實(shí)現(xiàn)了通信。
AsyncTask原理
1 逆趣、AsyncTask中有兩個(gè)線程池(SerialExecutor和THREAD_POOL_EXECUTOR)和一個(gè)Handler(InternalHandler)蝶溶,其中線程池SerialExecutor用于任務(wù)的排隊(duì),而線程池THREAD_POOL_EXECUTOR用于真正地執(zhí)行任務(wù),InternalHandler用于將執(zhí)行環(huán)境從線程池切換到主線程抖所。
2梨州、InternalHandler是一個(gè)靜態(tài)的Handler對(duì)象,為了能夠?qū)?zhí)行環(huán)境切換到主線程田轧,這就要求sHandler這個(gè)對(duì)象必須在主線程創(chuàng)建暴匠。由于靜態(tài)成員會(huì)在加載類的時(shí)候進(jìn)行初始化,因此這就變相要求AsyncTask的類必須在主線程中加載傻粘,否則同一個(gè)進(jìn)程中的AsyncTask都將無法正常工作每窖。
談?wù)剬?duì)RxJava的理解
RxJava是基于響應(yīng)式編程,基于事件流弦悉、實(shí)現(xiàn)異步操(類似于Android中的AsyncTask窒典、Handler作用)作的庫,基于事件流的鏈?zhǔn)秸{(diào)用稽莉,使得RxJava邏輯簡潔瀑志、使用簡單。RxJava原理是基于一種擴(kuò)展的觀察者模式污秆,有四種角色:被觀察者Observable 觀察者Observer 訂閱subscribe 事件Event劈猪。RxJava原理可總結(jié)為:被觀察者Observable通過訂閱(subscribe)按順序發(fā)送事件(Emitter)給觀察者(Observer), 觀察者按順序接收事件良拼、作出相應(yīng)的響應(yīng)動(dòng)作岸霹。
Android各版本新特性
1、Android5.0新特性:MaterialDesign設(shè)計(jì)風(fēng)格将饺、支持64位ART虛擬機(jī)贡避、通知詳情可以用戶自己設(shè)計(jì)。
2予弧、Android6.0新特性:動(dòng)態(tài)權(quán)限管理刮吧、支持快速充電的切換、支持文件夾拖拽應(yīng)用掖蛤、相機(jī)新增專業(yè)模式杀捻。
3、Android7.0新特性:多窗口支持蚓庭、V2簽名致讥、增強(qiáng)的Java8語言模式、夜間模式器赞。
4垢袱、Android8.0(O)新特性:優(yōu)化通知、畫中畫模式港柜、自動(dòng)填充框架请契、系統(tǒng)優(yōu)化咳榜。
5、Android9.0(P)新特性:室內(nèi)WIFI定位爽锥、“劉河亢”屏幕支持、安全增強(qiáng)氯夷。
6臣樱、Android10.0(Q)新特性:用戶存儲(chǔ)權(quán)限的變更、用戶的定位權(quán)限的變更腮考。
談一下一次完整的http請求
首先進(jìn)行DNS域名解析
- 三次握手建立TCP連接
- 客戶端向服務(wù)器發(fā)送請求命令
- 客戶端發(fā)送請求頭信息
- 服務(wù)器應(yīng)答 Http/1.1 200 OK
- 服務(wù)器返回相應(yīng)頭信息
- 服務(wù)器向客戶端發(fā)送數(shù)據(jù)
- 服務(wù)器關(guān)閉TCP連接
談一下一次完整的https請求
- 客戶端發(fā)起https請求
- 服務(wù)器必須要有一套數(shù)字證書雇毫,可以自己制作,也可以向權(quán)威機(jī)構(gòu)申請秸仙。這套證書其實(shí)就是一對(duì)公私鑰嘴拢。
- 服務(wù)器將自己的數(shù)字證書(含有公鑰、證書的頒發(fā)機(jī)構(gòu)等)發(fā)送給客戶端寂纪。
- 客戶端收到服務(wù)器端的數(shù)字證書之后席吴,會(huì)對(duì)其進(jìn)行驗(yàn)證,主要驗(yàn)證公鑰是否有效捞蛋,比如頒發(fā)機(jī)構(gòu)孝冒,過期時(shí)間等等。如果不通過拟杉,則彈出警告框庄涡。如果證書沒問題,則生成一個(gè)密鑰(對(duì)稱加密算法的密鑰搬设,其實(shí)是一個(gè)隨機(jī)值)穴店,并且用證書的公鑰對(duì)這個(gè)隨機(jī)值加密。
- 客戶端會(huì)發(fā)起https中的第二個(gè)請求拿穴,將加密之后的客戶端密鑰(隨機(jī)值)發(fā)送給服務(wù)器泣洞。
- 服務(wù)器接收到客戶端發(fā)來的密鑰之后,會(huì)用自己的私鑰對(duì)其進(jìn)行非對(duì)稱解密默色,解密之后得到客戶端密鑰球凰,然后用客戶端密鑰對(duì)返回?cái)?shù)據(jù)進(jìn)行對(duì)稱加密,這樣數(shù)據(jù)就變成了密文腿宰。
- 服務(wù)器將加密后的密文返回給客戶端呕诉。
- 客戶端收到服務(wù)器發(fā)返回的密文,用自己的密鑰(客戶端密鑰)對(duì)其進(jìn)行對(duì)稱解密吃度,得到服務(wù)器返回的數(shù)據(jù)甩挫。
布局性能優(yōu)化之Include、ViewStub规肴、Merge
- include標(biāo)簽常用于將布局中的公共部分提取出來供其他layout共用捶闸,以實(shí)現(xiàn)布局模塊化,也是平常我們設(shè)計(jì)布局時(shí)用的最多的夜畴。
- ViewStub就是一個(gè)寬高都為0的一個(gè)View拖刃,它默認(rèn)是不可見的删壮,只有通過調(diào)用setVisibility函數(shù)或者Inflate函數(shù)才會(huì)將其要裝載的目標(biāo)布局給加載出來,從而達(dá)到延遲加載的效果兑牡,這個(gè)要被加載的布局通過android:layout屬性來設(shè)置央碟。
- 在一個(gè)布局中包含一個(gè)布局時(shí),merge標(biāo)簽有助于消除視圖層次結(jié)構(gòu)中的冗余視圖組均函。如果是merge標(biāo)簽亿虽,那么直接將其中的子元素添加到merge標(biāo)簽parent中,這樣就保證了不會(huì)引入額外的層級(jí)苞也。
非UI線程是否可以刷新UI
非UI線程是可以刷新UI的洛勉,前提是它要擁有自己的ViewRoot。如果想直接創(chuàng)建ViewRoot實(shí)例如迟,你會(huì)發(fā)現(xiàn)找不到這個(gè)類收毫。但是可以通過WindowManager。
因?yàn)橥ǔ5淖泳€程更新UI的報(bào)錯(cuò)是ViewRootImpl類的checkThread函數(shù)拋出的殷勘,而ViewRootImpl在onResume中才會(huì)創(chuàng)建此再,所以在這之前子線程更新UI是不會(huì)報(bào)錯(cuò)的
class NonUiThread extends Thread{
@Override
public void run() {
Looper.prepare();
TextView tx = new TextView(MainActivity.this);
tx.setText("non-UiThread update textview");
WindowManager windowManager = MainActivity.this.getWindowManager();
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
200, 200, 200, 200, WindowManager.LayoutParams.FIRST_SUB_WINDOW,
WindowManager.LayoutParams.TYPE_TOAST,PixelFormat.OPAQUE);
windowManager.addView(tx, params);
Looper.loop();
}
}
Android ANR
Application Not Responding,應(yīng)用無響應(yīng)玲销。
發(fā)生場景:
- Service Timeout:比如前臺(tái)服務(wù)在20s內(nèi)未執(zhí)行完成输拇。
- BroadcastQueue Timeout:比如前臺(tái)廣播在10s內(nèi)未執(zhí)行完成。
- ContentProvider Timeout:內(nèi)容提供者,在publish過超時(shí)10s贤斜。
- InputDispatching Timeout: 輸入事件分發(fā)超時(shí)5s策吠,包括按鍵和觸摸事件。
導(dǎo)致ANR無響應(yīng)的常見原因 :
- 主線程阻塞 (避免死鎖的出現(xiàn)瘩绒,使用子線程來處理耗時(shí)操作或阻塞任務(wù))
- IO阻塞 (文件讀寫或數(shù)據(jù)庫操作放在子線程異步操作)
- CPU大量計(jì)算猴抹,內(nèi)存不足
定位分析:
- ActivityManager( 996): ANR in ... ANR發(fā)生在哪個(gè)應(yīng)用
- PID:8625: 產(chǎn)生ANR應(yīng)用的線程號(hào)
- ActivityManager( 996): Reason: Input dispatching timed out ANR產(chǎn)生的原因
- Load: 3.46 / 2.71 / 1.24 CPU前1分鐘、5分鐘草讶、15分鐘的CPU平均負(fù)載
- ActivityManager( 996): CPU usage from 94ms to 643ms later