Android基礎之其他

1. Android中的事件傳遞機制?

答:當我們的手指觸碰到屏幕,事件是按照Activity->ViewGroup->View這樣的流程到達最終響應觸摸事件的View的严望。而在事件分發(fā)過程中虏缸,涉及到三個最重要的方法:dispatchTouchEvent()、onInterceptTouchEvent()肠虽、onTouchEvent。我們的手指觸摸到屏幕的時候玛追,會觸發(fā)一個Action_Down類型的事件税课,當前頁面的Activity會首先做出相應,也就是說會走到Activity的dispatchTouchEvent()方法內痊剖。在這個方法內部有下面兩個邏輯:

調用getWindow.superDispatchTouchEvent()韩玩。

如果上一步返回true,則直接返回true陆馁;否則return自己的onTouchEvent()找颓。顯然,當getWindow.superDispatchTouchEvent()返回true叮贩,表示當前事件已經被消費掉击狮,無需調用onTouchEvent;否則代表事件并沒有被處理益老,因此需要調用Activity的onTouchEvent進行處理彪蓬。

我們都知道,getWindow()返回的是PhoneWindow捺萌,因此這句代碼本質上調用了PhoneWindow中的superDispatchTouchEvent()档冬。而后者實際上調用了mDecor.superDispatchTouchEvent(event)。這個mDecor也就是DecorView,它是FrameLayout的一個子類捣郊。在DecorView中的superDispatchTouchEvent(event)中調用的是super.dispatchTouchEvent()辽狈。因此,本質上調用的是ViewGroup的dispatchTouchEvent()呛牲。

到這里刮萌,事件已經從Activity傳遞到ViewGroup了。接下來我們分析ViewGroup娘扩。

在ViewGroup的dispatchTouchEvent()中邏輯大致如下:

通過onInterceptTouchEvent()判斷當前ViewGroup是否攔截着茸,默認的ViewGroup都是不攔截的;

如果攔截琐旁,則return自己的onTouchEvent()涮阔;

如果不攔截,則根據child.dispatchTouchEvent()的返回值判斷灰殴。如果返回true敬特,則return true;否則return自身的onTouchEvent()牺陶,在這里實現了未處理事件的向上傳遞伟阔。

通常情況下,ViewGroup 的 onInterceptTouchEvent() 都返回 false掰伸,表示不攔截皱炉。這里需要注意的是事件序列,比如Down事件狮鸭、Move事件…Up事件合搅,從 Down到 Up 是一個完整的事件序列,對應著手指從按下到抬起這一系列事件歧蕉,如果ViewGroup 攔截了 Down 事件灾部,那么后續(xù)事件都會交給這個 ViewGroup 的onTouchEvent。如果 ViewGroup 攔截的不是 Down 事件惯退,那么會給之前處理這個Down 事件的 View發(fā)送一個Action_Cancel 類型的事件梳猪,通知子View這個后續(xù)的事件序列已經被 ViewGroup 接管了,子 View 恢復之前的狀態(tài)即可蒸痹。

這里舉一個常見的例子:在一個 Recyclerview 中有很多的 Button,我們首先按下了一個 button呛哟,然后滑動一段距離再松開叠荠,這時候 Recyclerview 會跟著滑動,并不會觸發(fā)這個 button 的點擊事件扫责。這個例子中榛鼎,當我們按下 button 時,這個 button 接收到了 Action_Down 事件,正常情況下后續(xù)的事件序列應該由這個 button處理者娱。但我們滑動了一段距離抡笼,這時 Recyclerview 察覺到這是一個滑動操作,攔截了這個事件序列黄鳍,走了自身的 onTouchEvent()方法推姻,反映在屏幕上就是列表的滑動。而這時 button 仍然處于按下的狀態(tài)框沟,所以在攔截的時候需要發(fā)送一個 Action_Cancel 來通知 button 恢復之前狀態(tài)藏古。

事件分發(fā)最終會走到View的dispatchTouchEvent()中。在View的dispatchTouchEvent()中沒有onInterceptTouchEvent()忍燥,這里很容易理解拧晕,View沒有child,也就不存在攔截梅垄。View的dispatchTouchEvent()直接return了自己的onTouchEvent()厂捞。如果onTouchEvent()返回true代表事件被消費,否則未消費的事件會向上傳遞队丝,直到有View處理了事件或一直沒有消費靡馁,最終回到Activity的onTouchEvent()終止。

有時候會有人混淆onTouchEvent和onTouch炭玫。首先奈嘿,這兩個方法都在View的dispatchTouchEvent()中:

如果touchListener不為null,并且這個View是enable的吞加,而且onTouch返回true裙犹,都滿足時直接return true,走不到onTouchEvent()方法衔憨。

否則叶圃,就會觸發(fā)onTouchEvent()。因此onTouch優(yōu)先于onTouchEvent獲得事件處理權践图。

最后附上流程圖總結:

touch事件傳遞流程

參考:https://juejin.im/entry/58df5b33570c35005798493c

https://juejin.im/post/5b8f15e26fb9a01a031b12d9#heading-3

2. Handler的原理掺冠?

答:與Handler密切相關的還有Message、MessageQueue码党、Looper德崭。

Message。Message有兩個關鍵的成員變量:target揖盘、callback:

(1) target眉厨。就是發(fā)送消息的Handler

(2) callback。調用Handler.post(Runnable)時傳入的Runnable類型的任務兽狭。post事件的本質也是創(chuàng)建了一個Message憾股,將我們傳入的這個runnable賦值給創(chuàng)建的Message的callback這個成員變量鹿蜀。

MessageQueue。消息隊列用于存放消息服球,其中重點關注next()方法茴恰,它會返回下一個待處理的消息。

Looper斩熊。Looper消息輪詢器其實是連接Handler和消息隊列的核心往枣。想要在一個線程中創(chuàng)建一個Handler,首先要通過Looper.prepare()創(chuàng)建Looper座享,之后還得調用Looper.loop()開啟輪詢婉商。

(1) prepare()。這個方法做了兩件事:首先通過ThreadLocal.get()獲取當前線程中的Looper渣叛,如果不為空則拋出RuntimeException丈秩。否則創(chuàng)建Looper,并通過ThreadLocal.set(looper)將當前線程與剛剛創(chuàng)建的Looper綁定淳衙。值得注意的是蘑秽,上面的消息隊列的創(chuàng)建其實就是發(fā)生在Looper的構造函數中。

(2)loop()箫攀。這個方法開啟了整個事件機制的輪詢肠牲。其本質是開啟一個死循環(huán),不斷地通過MessageQueue的next()方法獲取消息msg靴跛。拿到消息后會調用msg.target.dispatchMessage()來做處理缀雳。綜上也就是調用handler.dispatchMessage()。

Handler梢睛。Handler重點在于發(fā)送消息和處理消息肥印。

(1)發(fā)送消息。其實發(fā)送消息除了 sendMessage 之外還有 sendMessageDelayed 和 post 以及 postDelayed 等等不同的方式绝葡。但它們的本質都是調用了 sendMessageAtTime深碱。在 sendMessageAtTime 這個方法中調用了 enqueueMessage。在 enqueueMessage 這個方法中做了兩件事:通過 msg.target = this 實現了消息與當前 handler 的綁定藏畅。然后通過 queue.enqueueMessage 實現了消息入隊敷硅。

(2)處理消息。 消息處理的核心其實就是dispatchMessage()這個方法愉阎。這個方法里面的邏輯很簡單绞蹦,先判斷 msg.callback 是否為 null,如果不為空則執(zhí)行這個 runnable榜旦。如果為空則會執(zhí)行我們的handleMessage方法坦辟。

3. ANR出現的情況有幾種? 怎么分析解決ANR問題章办?

答:ANR(Application Not responding)。Android中,主線程(UI線程)如果在規(guī)定時內沒有處理完相應工作藕届,就會出現ANR挪蹭。具體來說,ANR會在以下幾種情況中出現:

(1) 輸入事件(按鍵和觸摸事件)5s內沒被處理

(2) BroadcastReceiver的事件(onRecieve方法)在規(guī)定時間內沒處理完(前臺廣播為10s休偶,后臺廣播為60s)

(3) service 前臺20s后臺200s未完成啟動

(4) ContentProvider的publish在10s內沒進行完

分析ANR問題梁厉,需要結合Log以及trace文件。具體分析流程踏兜,可參照以下兩篇文章:

http://www.reibang.com/p/fa962a5fd939

https://blog.csdn.net/droyon/article/details/51099826

4. 內存泄露的場景有哪些词顾?內存泄漏分析工具使用方法?

答:常見的內存泄露有:

單例模式引起的內存泄露碱妆。

靜態(tài)變量導致的內存泄露肉盹。

非靜態(tài)內部類引起的內存泄露。

使用資源時疹尾,未及時關閉引起內存泄露上忍。

使用屬性動畫引起的內存泄露。

Webview導致的內存泄露纳本。

而對于內存泄露的檢測窍蓝,常用的工具有LeakCanary、MAT(Memory Analyer Tools)繁成、Android Studio自帶的Profiler吓笙。關于用法,網上教程很多巾腕,可自行查閱面睛,下面兩個經供參考:

三種用法、MAT

同時附上官方Android Profiler教程

5. 常用的設計模式有哪些祠墅?是否了解責任鏈模式侮穿?

答:單例模式,觀察者模式毁嗦,工廠模式亲茅,建造者模式,構造者模式狗准,中間者模式克锣,橋接模式,適配器模式等等腔长。

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末袭祟,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子捞附,更是在濱河造成了極大的恐慌巾乳,老刑警劉巖您没,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異胆绊,居然都是意外死亡氨鹏,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進店門压状,熙熙樓的掌柜王于貴愁眉苦臉地迎上來仆抵,“玉大人,你說我怎么就攤上這事种冬×统螅” “怎么了?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵娱两,是天一觀的道長莺匠。 經常有香客問我,道長谷婆,這世上最難降的妖魔是什么慨蛙? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮纪挎,結果婚禮上期贫,老公的妹妹穿的比我還像新娘。我一直安慰自己异袄,他們只是感情好通砍,可當我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著烤蜕,像睡著了一般封孙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上讽营,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天虎忌,我揣著相機與錄音,去河邊找鬼橱鹏。 笑死膜蠢,一個胖子當著我的面吹牛,可吹牛的內容都是我干的莉兰。 我是一名探鬼主播挑围,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼糖荒!你這毒婦竟也來了杉辙?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤捶朵,失蹤者是張志新(化名)和其女友劉穎蜘矢,沒想到半個月后狂男,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡硼端,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年并淋,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片珍昨。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖句喷,靈堂內的尸體忽然破棺而出镣典,到底是詐尸還是另有隱情,我是刑警寧澤唾琼,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布兄春,位于F島的核電站,受9級特大地震影響锡溯,放射性物質發(fā)生泄漏赶舆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一祭饭、第九天 我趴在偏房一處隱蔽的房頂上張望芜茵。 院中可真熱鬧,春花似錦倡蝙、人聲如沸九串。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽猪钮。三九已至,卻和暖如春胆建,著一層夾襖步出監(jiān)牢的瞬間烤低,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工笆载, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留扑馁,地道東北人。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓宰译,卻偏偏與公主長得像檐蚜,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子沿侈,可洞房花燭夜當晚...
    茶點故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內容