字节跳动资深面试官亲述:面试应该注意哪些问题?
01面試=做匹配
面試官的根本目的在于考察你這個(gè)人是否與招聘崗位相匹配,衡量能否勝任工作,我們?cè)诿嬖囍幸龅降木褪亲屆嬖嚬傧嘈盼覀兡軌蚺c應(yīng)聘崗位相匹配。
針對(duì)一些面試題做了總結(jié):
1.請(qǐng)簡(jiǎn)單進(jìn)行一下自我介紹
首先請(qǐng)報(bào)出自己的姓名和身份。可能應(yīng)試者與面試考官打招呼時(shí),已經(jīng)將此告訴了對(duì)方,而且考官們完全可以從你的報(bào)名表、簡(jiǎn)歷等材料中了解這些情況,但仍請(qǐng)你主動(dòng)提及。這是禮貌的需要,還可以加深考官對(duì)你的印象。
其次,你可以簡(jiǎn)單地介紹一下你的學(xué)歷、工作經(jīng)歷等基本個(gè)人情況。請(qǐng)?zhí)峁┙o考官關(guān)于你個(gè)人情況的基本的、完整的信息,如:學(xué)歷、工作經(jīng)歷、家庭概況、興趣愛(ài)好、理想與報(bào)負(fù)等。 這部分的陳述務(wù)必簡(jiǎn)明扼要、抓住要點(diǎn)。例如介紹自己的學(xué)歷,一般只需談本專(zhuān)科以上的學(xué)歷。工作單位如果多,選幾個(gè)有代表性的或者你認(rèn)為重要的介紹,就可以了,但這些內(nèi)容一定要和面試及應(yīng)考職位有關(guān)系。請(qǐng)保證敘述的線(xiàn)索清晰,一個(gè)結(jié)構(gòu)混亂、內(nèi)容過(guò)長(zhǎng)的開(kāi)場(chǎng)自,會(huì)給考官們留下雜亂無(wú)章、個(gè)性不清晰的印象,并且讓考官倦怠,削弱對(duì)繼續(xù)進(jìn)行的面試的興趣和注意力。
應(yīng)試者還要注意這部份內(nèi)容應(yīng)與個(gè)人簡(jiǎn)歷、報(bào)名材料上的有關(guān)內(nèi)容相一致,不要有出入。在介紹這些內(nèi)容時(shí),應(yīng)避免書(shū)面語(yǔ)言的嚴(yán)整與拘束,而使用靈活的口頭語(yǔ)進(jìn)行組織。這些個(gè)人基本情況的介紹沒(méi)有對(duì)或錯(cuò)的問(wèn)題——都屬于中性問(wèn)題,但如果因此而大意就不妥了。
接下來(lái)由這部份個(gè)人基本情況,自然地過(guò)渡到一兩個(gè)自己本科或工作期間圓滿(mǎn)完成的事件,以這一兩個(gè)例子來(lái)形象地、明晰他說(shuō)明自己的經(jīng)驗(yàn)與能力,例如:在學(xué)校擔(dān)任學(xué)生干部時(shí)成功組織的活動(dòng);或者如何投入到社會(huì)實(shí)踐中,利用自己的專(zhuān)長(zhǎng)為社會(huì)公眾服務(wù);或者自己在專(zhuān)業(yè)上取得的重要成績(jī)以及出色的學(xué)術(shù)成就。
接下來(lái)要著重結(jié)合你的職業(yè)理想說(shuō)明你應(yīng)考這個(gè)公務(wù)員職位的原因,這一點(diǎn)相當(dāng)重要。你可以談你對(duì)應(yīng)考單位或職務(wù)的認(rèn)識(shí)了解,說(shuō)明你選擇這個(gè)單位或職務(wù)的強(qiáng)烈愿望。原先有工作單位的應(yīng)試者應(yīng)解釋清楚自己放棄原來(lái)的工作而做出新的職業(yè)選擇的原因。你還可以談如果你被錄取,那么你將怎樣盡職盡責(zé)地工作,并不斷根據(jù)需要完善和發(fā)展自己。當(dāng)然這些都應(yīng)密切聯(lián)系你的價(jià)值觀(guān)與職業(yè)觀(guān)。不過(guò),如果你將自己描述為不食人間煙火的、不計(jì)較個(gè)人利益的“圣人”,那么考官們對(duì)你的求職動(dòng)機(jī)的信任,就要大打折扣了。
這里我們介紹了一條清晰的線(xiàn)索,便于你組織你的自我介紹。為了保證結(jié)構(gòu)明確,有條有理,你可以多用短句子以便于口語(yǔ)表述,并且在段與段之間使用過(guò)渡句子,口語(yǔ)也要注意思路、敘述語(yǔ)言的流暢,盡量避免顛三倒四,同一句話(huà)反復(fù)說(shuō)幾遍的“粘糊勁,同時(shí)不要用過(guò)于隨便的表述。
2.你認(rèn)為自己最大的缺點(diǎn)是什么?
思路:
1、 不宜說(shuō)自己沒(méi)缺點(diǎn)。
2、 不宜把那些明顯的優(yōu)點(diǎn)說(shuō)成缺點(diǎn)。
3、 不宜說(shuō)出嚴(yán)重影響所應(yīng)聘工作的缺點(diǎn)。
4、 不宜說(shuō)出令人不放心、不舒服的缺點(diǎn)。
5、 可以說(shuō)出一些對(duì)于所應(yīng)聘工作“無(wú)關(guān)緊要”的缺點(diǎn),甚至是一些表面上看是缺點(diǎn),從工作的角度看卻是優(yōu)點(diǎn)的缺點(diǎn)。
答:我的工作執(zhí)行力很高,領(lǐng)導(dǎo)給我安排的任務(wù)我也能較快的完成,但是可能在工作的時(shí)候會(huì)少一些深入的獨(dú)立思考,對(duì)整個(gè)工作的安排缺乏戰(zhàn)略眼光,對(duì)于這方面能力需要我進(jìn)一步的努力,我也將繼續(xù)學(xué)習(xí),通過(guò)閱讀、向前輩請(qǐng)教等改善自己的不足。
3.你是如何看待加班的?
答:工作中難免會(huì)出現(xiàn)各種各樣的突發(fā)狀況,我完全可以接受突發(fā)臨時(shí)性的加班,以確保項(xiàng)目或者工作的順利推進(jìn),因?yàn)檫@些都是我應(yīng)當(dāng)負(fù)責(zé)的。但是以加班為榮,或者只是為了其他人都沒(méi)走的這種加班,我想我無(wú)法接受。如果是我自身的原因?qū)е聼o(wú)法順利完成工作而不得不加班,那么我也會(huì)尋找原因,提高個(gè)人工作效率,嘗試解決問(wèn)題。
4.你還有什么想問(wèn)的嗎?
答:如果我有幸加入貴公司/團(tuán)隊(duì)/部門(mén),那么前期我將主要負(fù)責(zé)哪方面的工作內(nèi)容呢?/“您覺(jué)得我要?jiǎng)偃芜@個(gè)崗位,還需要在哪方面多下功夫呢?”
Tips:從工作體驗(yàn)、工作內(nèi)容、崗位發(fā)展等角度入手都是很不錯(cuò)的選擇。
02 Android面試中有哪些常見(jiàn)問(wèn)題匯總&答題思路
目錄:
1.網(wǎng)絡(luò)
2.Java 基礎(chǔ)&容器&同步&設(shè)計(jì)模式
3.Java 虛擬機(jī)&內(nèi)存結(jié)構(gòu)&GC&類(lèi)加載&四種引用&動(dòng)態(tài)代理
4.Android 基礎(chǔ)&性能優(yōu)化&Framwork
5.Android 模塊化&熱修復(fù)&熱更新&打包&混淆&壓縮
6.音視頻&FFmpeg&播放器
1、網(wǎng)絡(luò)
網(wǎng)絡(luò)協(xié)議模型
**應(yīng)用層:**負(fù)責(zé)處理特定的應(yīng)用程序細(xì)節(jié)
HTTP、FTP、DNS
**傳輸層:**為兩臺(tái)主機(jī)提供端到端的基礎(chǔ)通信
TCP、UDP
**網(wǎng)絡(luò)層:**控制分組傳輸、路由選擇等
IP
**鏈路層:**操作系統(tǒng)設(shè)備驅(qū)動(dòng)程序、網(wǎng)卡相關(guān)接口
TCP 和 UDP 區(qū)別
TCP 連接;可靠;有序;面向字節(jié)流;速度慢;較重量;全雙工;適用于文件傳輸、瀏覽器等
全雙工:A 給 B 發(fā)消息的同時(shí),B 也能給 A 發(fā)
半雙工:A 給 B 發(fā)消息的同時(shí),B 不能給 A 發(fā)
UDP 無(wú)連接;不可靠;無(wú)序;面向報(bào)文;速度快;輕量;適用于即時(shí)通訊、視頻通話(huà)等
TCP 三次握手
A:你能聽(tīng)到嗎?
B:我能聽(tīng)到,你能聽(tīng)到嗎?
A:我能聽(tīng)到,開(kāi)始吧
A 和 B 兩方都要能確保:我說(shuō)的話(huà),你能聽(tīng)到;你說(shuō)的話(huà),我能聽(tīng)到。所以需要三次握手
TCP 四次揮手
A:我說(shuō)完了
B:我知道了,等一下,我可能還沒(méi)說(shuō)完
B:我也說(shuō)完了
A:我知道了,結(jié)束吧
B 收到 A 結(jié)束的消息后 B 可能還沒(méi)說(shuō)完,沒(méi)法立即回復(fù)結(jié)束標(biāo)示,只能等說(shuō)完后再告訴 A :我說(shuō)完了。
POST 和 GET 區(qū)別
Get 參數(shù)放在 url 中;Post 參數(shù)放在 request Body 中
Get 可能不安全,因?yàn)閰?shù)放在 url 中
HTTPS
HTTP 是超文本傳輸協(xié)議,明文傳輸;HTTPS 使用 SSL 協(xié)議對(duì) HTTP 傳輸數(shù)據(jù)進(jìn)行了加密
HTTP 默認(rèn) 80 端口;HTTPS 默認(rèn) 443 端口
優(yōu)點(diǎn):安全
缺點(diǎn):費(fèi)時(shí)、SSL 證書(shū)收費(fèi),加密能力還是有限的,但是比 HTTP 強(qiáng)多了
2、Java 基礎(chǔ)&容器&同步&設(shè)計(jì)模式
StringBuilder、StringBuffer、+、String.concat 鏈接字符串:
StringBuffer 線(xiàn)程安全,StringBuilder 線(xiàn)程不安全
+實(shí)際上是用 StringBuilder 來(lái)實(shí)現(xiàn)的,所以非循環(huán)體可以直接用 +,循環(huán)體不行,因?yàn)闀?huì)頻繁創(chuàng)建 StringBuilder
String.concat 實(shí)質(zhì)是 new String ,效率也低,耗時(shí)排序:StringBuilder < StringBuffer < concat < +
Java 泛型擦除
修飾成員變量等類(lèi)結(jié)構(gòu)相關(guān)的泛型不會(huì)被擦除
容器類(lèi)泛型會(huì)被擦除
ArrayList、LinkedList
ArrayList
基于數(shù)組實(shí)現(xiàn),查找快:o(1),增刪慢:o(n)
初始容量為10,擴(kuò)容通過(guò) System.arrayCopy 方法
LinkedList
基于雙向鏈表實(shí)現(xiàn),查找慢:o(n),增刪快:o(1)
封裝了隊(duì)列和棧的調(diào)用
HashMap 、HashTable
HashMap
基于數(shù)組和鏈表實(shí)現(xiàn),數(shù)組是 HashMap 的主體;鏈表是為解決哈希沖突而存在的
當(dāng)發(fā)生哈希沖突且鏈表 size 大于閾值時(shí)會(huì)擴(kuò)容,JAVA 8 會(huì)將鏈表轉(zhuǎn)為紅黑樹(shù)提高性能
允許 key/value 為 null
HashTable
數(shù)據(jù)結(jié)構(gòu)和 HashMap 一樣
不允許 value 為 null
線(xiàn)程安全
ArrayMap、SparseArray
ArrayMap
1.基于兩個(gè)數(shù)組實(shí)現(xiàn),一個(gè)存放 hash;一個(gè)存放鍵值對(duì)。擴(kuò)容的時(shí)候只需要數(shù)組拷貝,不需要重建哈希表
2.內(nèi)存利用率高
3.不適合存大量數(shù)據(jù),因?yàn)闀?huì)對(duì) key 進(jìn)行二分法查找(1000以下)
SparseArray
1.基于兩個(gè)數(shù)組實(shí)現(xiàn),int 做 key
2.內(nèi)存利用率高
3.不適合存大量數(shù)據(jù),因?yàn)闀?huì)對(duì) key 進(jìn)行二分法查找(1000以下)
volatile 關(guān)鍵字
只能用來(lái)修飾變量,適用修飾可能被多線(xiàn)程同時(shí)訪(fǎng)問(wèn)的變量
相當(dāng)于輕量級(jí)的 synchronized,volatitle 能保證有序性(禁用指令重排序)、可見(jiàn)性;后者還能保證原子性
變量位于主內(nèi)存中,每個(gè)線(xiàn)程還有自己的工作內(nèi)存,變量在自己線(xiàn)程的工作內(nèi)存中有份拷貝,線(xiàn)程直接操作的是這個(gè)拷貝
被 volatile 修飾的變量改變后會(huì)立即同步到主內(nèi)存,保持變量的可見(jiàn)性。
雙重檢查單例,為什么要加 volatile?
1.volatile想要解決的問(wèn)題是,在另一個(gè)線(xiàn)程中想要使用instance,發(fā)現(xiàn)instance!=null,但是實(shí)際上instance還未初始化完畢這個(gè)問(wèn)題
2.將instance =newInstance();拆分為3句話(huà)是。1.分配內(nèi)存2.初始化3.將instance指向分配的內(nèi)存空
3.volatile可以禁止指令重排序,確保先執(zhí)行2,后執(zhí)行3
wait 和 sleep
sleep 是 Thread 的靜態(tài)方法,可以在任何地方調(diào)用
wait 是 Object 的成員方法,只能在 synchronized 代碼塊中調(diào)用,否則會(huì)報(bào) IllegalMonitorStateException 非法監(jiān)控狀態(tài)異常
sleep 不會(huì)釋放共享資源鎖,wait 會(huì)釋放共享資源鎖
lock 和 synchronized
synchronized 是 Java 關(guān)鍵字,內(nèi)置特性;Lock 是一個(gè)接口
synchronized 會(huì)自動(dòng)釋放鎖;lock 需要手動(dòng)釋放,所以需要寫(xiě)到 try catch 塊中并在 finally 中釋放鎖
synchronized 無(wú)法中斷等待鎖;lock 可以中斷
Lock 可以提高多個(gè)線(xiàn)程進(jìn)行讀/寫(xiě)操作的效率
競(jìng)爭(zhēng)資源激烈時(shí),lock 的性能會(huì)明顯的優(yōu)于 synchronized
可重入鎖
定義:已經(jīng)獲取到鎖后,再次調(diào)用同步代碼塊/嘗試獲取鎖時(shí)不必重新去申請(qǐng)鎖,可以直接執(zhí)行相關(guān)代碼
ReentrantLock 和 synchronized 都是可重入鎖
公平鎖
定義:等待時(shí)間最久的線(xiàn)程會(huì)優(yōu)先獲得鎖
非公平鎖無(wú)法保證哪個(gè)線(xiàn)程獲取到鎖,synchronized 就是非公平鎖
ReentrantLock 默認(rèn)時(shí)非公平鎖,可以設(shè)置為公平鎖
樂(lè)觀(guān)鎖和悲觀(guān)鎖
**悲觀(guān)鎖:**線(xiàn)程一旦得到鎖,其他線(xiàn)程就掛起等待,適用于寫(xiě)入操作頻繁的場(chǎng)景;synchronized 就是悲觀(guān)鎖
**樂(lè)觀(guān)鎖:**假設(shè)沒(méi)有沖突,不加鎖,更新數(shù)據(jù)時(shí)判斷該數(shù)據(jù)是否過(guò)期,過(guò)期的話(huà)則不進(jìn)行數(shù)據(jù)更新,適用于讀取操作頻繁的場(chǎng)景
**樂(lè)觀(guān)鎖 CAS:**Compare And Swap,更新數(shù)據(jù)時(shí)先比較原值是否相等,不相等則表示數(shù)據(jù)過(guò)去,不進(jìn)行數(shù)據(jù)更新
****樂(lè)觀(guān)鎖實(shí)現(xiàn):AtomicInteger、AtomicLong、AtomicBoolean
死鎖 4 個(gè)必要條件
互斥
占有且等待
不可搶占
循環(huán)等待
synchronized 原理
每個(gè)對(duì)象都有一個(gè)監(jiān)視器鎖:monitor,同步代碼塊會(huì)執(zhí)行 monitorenter 開(kāi)始,motnitorexit 結(jié)束
wait/notify 就依賴(lài) monitor 監(jiān)視器,所以在非同步代碼塊中執(zhí)行會(huì)報(bào) IllegalMonitorStateException 異常
3、Java 虛擬機(jī)&內(nèi)存結(jié)構(gòu)&GC&類(lèi)加載&四種引用&動(dòng)態(tài)代理
JVM
定義:可以理解成一個(gè)虛構(gòu)的計(jì)算機(jī),解釋自己的字節(jié)碼指令集映射到本地 CPU 或 OS 的指令集,上層只需關(guān)注 Class 文件,與操作系統(tǒng)無(wú)關(guān),實(shí)現(xiàn)跨平臺(tái)
Kotlin 就是能解釋成 Class 文件,所以可以跑在 JVM 上
JVM 內(nèi)存模型
Java 多線(xiàn)程之間是通過(guò)共享內(nèi)存來(lái)通信的,每個(gè)線(xiàn)程都有自己的本地內(nèi)存
共享變量存放于主內(nèi)存中,線(xiàn)程會(huì)拷貝一份共享變量到本地內(nèi)存
volatile 關(guān)鍵字就是給內(nèi)存模型服務(wù)的,用來(lái)保證內(nèi)存可見(jiàn)性和順序性
JVM 內(nèi)存結(jié)構(gòu)
線(xiàn)程私有:
1.程序計(jì)數(shù)器:記錄正在執(zhí)行的字節(jié)碼指令地址,若正在執(zhí)行 Native 方法則為空
2.虛擬機(jī)棧:執(zhí)行方法時(shí)把方法所需數(shù)據(jù)存為一個(gè)棧幀入棧,執(zhí)行完后出棧
3.本地方法棧:同虛擬機(jī)棧,但是針對(duì)的是 Native 方法
線(xiàn)程共享:
1.堆:存儲(chǔ) Java 實(shí)例,GC 主要區(qū)域,分代收集 GC 方法會(huì)吧堆劃分為新生代、老年代
2.方法區(qū):存儲(chǔ)類(lèi)信息,常量池,靜態(tài)變量等數(shù)據(jù)
GC
回收區(qū)域:只針對(duì)堆、方法區(qū);線(xiàn)程私有區(qū)域數(shù)據(jù)會(huì)隨線(xiàn)程結(jié)束銷(xiāo)毀,不用回收
回收類(lèi)型:
1.堆中的對(duì)象
分代收集 GC 方法會(huì)吧堆劃分為新生代、老年代
新生代:新建小對(duì)象會(huì)進(jìn)入新生代;通過(guò)復(fù)制算法回收對(duì)象
老年代:新建大對(duì)象及老對(duì)象會(huì)進(jìn)入老年代;通過(guò)標(biāo)記-清除算法回收對(duì)象
2.方法區(qū)中的類(lèi)信息、常量池
判斷一個(gè)對(duì)象是否可被回收:
1.引用計(jì)數(shù)法
缺點(diǎn):循環(huán)引用
2.可達(dá)性分析法
定義:從 GC ROOT 開(kāi)始搜索,不可達(dá)的對(duì)象都是可以被回收的
GC ROOT
1.虛擬機(jī)棧/本地方法棧中引用的對(duì)象
2.方法區(qū)中常量/靜態(tài)變量引用的對(duì)象
四種引用
強(qiáng)引用:不會(huì)被回收
軟引用:內(nèi)存不足時(shí)會(huì)被回收
弱引用:gc 時(shí)會(huì)被回收
虛引用:無(wú)法通過(guò)虛引用得到對(duì)象,可以監(jiān)聽(tīng)對(duì)象的回收
ClassLoader
類(lèi)的生命周期:
1.加載;2.驗(yàn)證;3.準(zhǔn)備;4.解析;5.初始化;6.使用;7.卸載
類(lèi)加載過(guò)程:
1.加載:獲取類(lèi)的二進(jìn)制字節(jié)流;生成方法區(qū)的運(yùn)行時(shí)存儲(chǔ)結(jié)構(gòu);在內(nèi)存中生成 Class 對(duì)象
2.驗(yàn)證:確保該 Class 字節(jié)流符合虛擬機(jī)要求
3.準(zhǔn)備:初始化靜態(tài)變量
4.解析:將常量池的符號(hào)引用替換為直接引用
5.初始化:執(zhí)行靜態(tài)塊代碼、類(lèi)變量賦值
類(lèi)加載時(shí)機(jī):
1.實(shí)例化對(duì)象
2.調(diào)用類(lèi)的靜態(tài)方法
3.調(diào)用類(lèi)的靜態(tài)變量(放入常量池的常量除外)
類(lèi)加載器:負(fù)責(zé)加載 class 文件
分類(lèi):
1.引導(dǎo)類(lèi)加載器 - 沒(méi)有父類(lèi)加載器
2.拓展類(lèi)加載器 - 繼承自引導(dǎo)類(lèi)加載器
3.系統(tǒng)類(lèi)加載器 - 繼承自拓展類(lèi)加載器
雙親委托模型:
當(dāng)要加載一個(gè) class 時(shí),會(huì)先逐層向上讓父加載器先加載,加載失敗才會(huì)自己加載
為什么叫雙親?不考慮自定義加載器,系統(tǒng)類(lèi)加載器需要網(wǎng)上詢(xún)問(wèn)兩層,所以叫雙親
判斷是否是同一個(gè)類(lèi)時(shí),除了類(lèi)信息,還必須時(shí)同一個(gè)類(lèi)加載器
優(yōu)點(diǎn):
防止重復(fù)加載,父加載器加載過(guò)了就沒(méi)必要加載了
安全,防止篡改核心庫(kù)類(lèi)
動(dòng)態(tài)代理原理及實(shí)現(xiàn)
InvocationHandler 接口,動(dòng)態(tài)代理類(lèi)需要實(shí)現(xiàn)這個(gè)接口
Proxy.newProxyInstance,用于動(dòng)態(tài)創(chuàng)建代理對(duì)象
Retrofit 應(yīng)用: Retrofit 通過(guò)動(dòng)態(tài)代理,為我們定義的請(qǐng)求接口都生成一個(gè)動(dòng)態(tài)代理對(duì)象,實(shí)現(xiàn)請(qǐng)求
4、Android 基礎(chǔ)&性能優(yōu)化&Framwork
Activity 啟動(dòng)模式
standard 標(biāo)準(zhǔn)模式
singleTop 棧頂復(fù)用模式,
推送點(diǎn)擊消息界面
singleTask 棧內(nèi)復(fù)用模式,
首頁(yè)
singleInstance 單例模式,單獨(dú)位于一個(gè)任務(wù)棧中
撥打電話(huà)界面
細(xì)節(jié):
taskAffinity:任務(wù)相關(guān)性,用于指定任務(wù)棧名稱(chēng),默認(rèn)為應(yīng)用包名
allowTaskReparenting:允許轉(zhuǎn)移任務(wù)棧
View 工作原理
DecorView (FrameLayout)
LinearLayout
titlebar
Content
調(diào)用 setContentView 設(shè)置的 View
ViewRoot 的 performTraversals 方法調(diào)用觸發(fā)開(kāi)始 View 的繪制,然后會(huì)依次調(diào)用:
performMeasure:遍歷 View 的 measure 測(cè)量尺寸
performLayout:遍歷 View 的 layout 確定位置
performDraw:遍歷 View 的 draw 繪制
事件分發(fā)機(jī)制
一個(gè) MotionEvent 產(chǎn)生后,按 Activity -> Window -> decorView -> View 順序傳遞,View 傳遞過(guò)程就是事件分發(fā),主要依賴(lài)三個(gè)方法:
dispatchTouchEvent:用于分發(fā)事件,只要接受到點(diǎn)擊事件就會(huì)被調(diào)用,返回結(jié)果表示是否消耗了當(dāng)前事件
onInterceptTouchEvent:用于判斷是否攔截事件,當(dāng) ViewGroup 確定要攔截事件后,該事件序列都不會(huì)再觸發(fā)調(diào)用此 ViewGroup 的 onIntercept
onTouchEvent:用于處理事件,返回結(jié)果表示是否處理了當(dāng)前事件,未處理則傳遞給父容器處理
細(xì)節(jié):
一個(gè)事件序列只能被一個(gè) View 攔截且消耗
View 沒(méi)有 onIntercept 方法,直接調(diào)用 onTouchEvent 處理
OnTouchListener 優(yōu)先級(jí)比 OnTouchEvent 高,onClickListener 優(yōu)先級(jí)最低
requestDisallowInterceptTouchEvent 可以屏蔽父容器 onIntercet 方法的調(diào)用
Window 、 WindowManager、WMS、SurfaceFlinger
**Window:**抽象概念不是實(shí)際存在的,而是以 View 的形式存在,通過(guò) PhoneWindow 實(shí)現(xiàn)
**WindowManager:**外界訪(fǎng)問(wèn) Window 的入口,內(nèi)部與 WMS 交互是個(gè) IPC 過(guò)程
**WMS:**管理窗口 Surface 的布局和次序,作為系統(tǒng)級(jí)服務(wù)單獨(dú)運(yùn)行在一個(gè)進(jìn)程
**SurfaceFlinger:**將 WMS 維護(hù)的窗口按一定次序混合后顯示到屏幕上
View 動(dòng)畫(huà)、幀動(dòng)畫(huà)及屬性動(dòng)畫(huà)
View 動(dòng)畫(huà):
作用對(duì)象是 View,可用 xml 定義,建議 xml 實(shí)現(xiàn)比較易讀
支持四種效果:平移、縮放、旋轉(zhuǎn)、透明度
幀動(dòng)畫(huà):
通過(guò) AnimationDrawable 實(shí)現(xiàn),容易 OOM
屬性動(dòng)畫(huà):
可作用于任何對(duì)象,可用 xml 定義,Android 3 引入,建議代碼實(shí)現(xiàn)比較靈活
包括 ObjectAnimator、ValuetAnimator、AnimatorSet
時(shí)間插值器:根據(jù)時(shí)間流逝的百分比計(jì)算當(dāng)前屬性改變的百分比
系統(tǒng)預(yù)置勻速、加速、減速等插值器
類(lèi)型估值器:根據(jù)當(dāng)前屬性改變的百分比計(jì)算改變后的屬性值
系統(tǒng)預(yù)置整型、浮點(diǎn)、色值等類(lèi)型估值器
使用注意事項(xiàng):
避免使用幀動(dòng)畫(huà),容易OOM
界面銷(xiāo)毀時(shí)停止動(dòng)畫(huà),避免內(nèi)存泄漏
開(kāi)啟硬件加速,提高動(dòng)畫(huà)流暢性 ,硬件加速:
將 cpu 一部分工作分擔(dān)給 gpu ,使用 gpu 完成繪制工作
從工作分?jǐn)偤屠L制機(jī)制兩個(gè)方面優(yōu)化了繪制速度
Handler、MessageQueue、Looper
Handler:開(kāi)發(fā)直接接觸的類(lèi),內(nèi)部持有 MessageQueue 和 Looper
MessageQueue:消息隊(duì)列,內(nèi)部通過(guò)單鏈表存儲(chǔ)消息
Looper:內(nèi)部持有 MessageQueue,循環(huán)查看是否有新消息,有就處理,沒(méi)就阻塞
如何實(shí)現(xiàn)阻塞:通過(guò) nativePollOnce 方法,基于 Linux epoll 事件管理機(jī)制
為什么主線(xiàn)程不會(huì)因?yàn)?Looper 阻塞:系統(tǒng)每 16ms 會(huì)發(fā)送一個(gè)刷新 UI 消息喚醒
MVC、MVP、MVVM
MVP:Model:處理數(shù)據(jù);View:控制視圖;Presenter:分離 Activity 和 Model
MVVM:Model:處理獲取保存數(shù)據(jù);View:控制視圖;ViewModel:數(shù)據(jù)容器
使用 Jetpack 組件架構(gòu)的 LiveData、ViewModel 便捷實(shí)現(xiàn) MVVM
Serializable、Parcelable
Serializable :Java 序列化方式,適用于存儲(chǔ)和網(wǎng)絡(luò)傳輸,serialVersionUID 用于確定反序列化和類(lèi)版本是否一致,不一致時(shí)反序列化回失敗
Parcelable :Android 序列化方式,適用于組件通信數(shù)據(jù)傳遞,性能高,因?yàn)椴幌?Serializable 一樣有大量反射操作,頻繁 GC
Binder
Android 進(jìn)程間通信的中流砥柱,基于客戶(hù)端-服務(wù)端通信方式
使用 mmap 一次數(shù)據(jù)拷貝實(shí)現(xiàn) IPC,傳統(tǒng) IPC:用戶(hù)A空間->內(nèi)核->用戶(hù)B空間;mmap 將內(nèi)核與用戶(hù)B空間映射,實(shí)現(xiàn)直接從用戶(hù)A空間->用戶(hù)B空間
BinderPool 可避免創(chuàng)建多 Service
IPC 方式
Intent extras、Bundle:要求傳遞數(shù)據(jù)能被序列化,實(shí)現(xiàn) Parcelable、Serializable ,適用于四大組件通信
文件共享:適用于交換簡(jiǎn)單的數(shù)據(jù)實(shí)時(shí)性不高的場(chǎng)景
AIDL:AIDL 接口實(shí)質(zhì)上是系統(tǒng)提供給我們可以方便實(shí)現(xiàn) BInder 的工具
Android Interface Definition Language,可實(shí)現(xiàn)跨進(jìn)程調(diào)用方法
服務(wù)端:將暴漏給客戶(hù)端的接口聲明在 AIDL 文件中,創(chuàng)建 Service 實(shí)現(xiàn) AIDL 接口并監(jiān)聽(tīng)客戶(hù)端連接請(qǐng)求
客戶(hù)端:綁定服務(wù)端 Service ,綁定成功后拿到服務(wù)端 Binder 對(duì)象轉(zhuǎn)為 AIDL 接口調(diào)用
RemoteCallbackList 實(shí)現(xiàn)跨進(jìn)程接口監(jiān)聽(tīng),同個(gè) Binder 對(duì)象做 key 存儲(chǔ)客戶(hù)端注冊(cè)的 listener
監(jiān)聽(tīng) Binder 斷開(kāi):1.Binder.linkToDeath 設(shè)置死亡代理;2. onServiceDisconnected 回調(diào)
Messenger:基于 AIDL 實(shí)現(xiàn),服務(wù)端串行處理,主要用于傳遞消息,適用于低并發(fā)一對(duì)多通信
ContentProvider:基于 Binder 實(shí)現(xiàn),適用于一對(duì)多進(jìn)程間數(shù)據(jù)共享
Socket:TCP、UDP,適用于網(wǎng)絡(luò)數(shù)據(jù)交換
Android 系統(tǒng)啟動(dòng)流程
按電源鍵 -> 加載引導(dǎo)程序 BootLoader 到 RAM -> 執(zhí)行 BootLoader 程序啟動(dòng)內(nèi)核 -> 啟動(dòng) init 進(jìn)程 -> 啟動(dòng) Zygote 和各種守護(hù)進(jìn)程 ->
啟動(dòng) System Server 服務(wù)進(jìn)程開(kāi)啟 AMS、WMS 等 -> 啟動(dòng) Launcher 應(yīng)用進(jìn)程
App 啟動(dòng)流程
Launcher 中點(diǎn)擊一個(gè)應(yīng)用圖標(biāo) -> 通過(guò) AMS 查找應(yīng)用進(jìn)程,若不存在就通過(guò) Zygote 進(jìn)程 fork
進(jìn)程保活
進(jìn)程優(yōu)先級(jí):1.前臺(tái)進(jìn)程 ;2.可見(jiàn)進(jìn)程;3.服務(wù)進(jìn)程;4.后臺(tái)進(jìn)程;5.空進(jìn)程
進(jìn)程被 kill 場(chǎng)景:1.切到后臺(tái)內(nèi)存不足時(shí)被殺;2.切到后臺(tái)廠(chǎng)商省電機(jī)制殺死;3.用戶(hù)主動(dòng)清理
保活方式:
1.Activity 提權(quán):掛一個(gè) 1像素 Activity 將進(jìn)程優(yōu)先級(jí)提高到前臺(tái)進(jìn)程
2.Service 提權(quán):啟動(dòng)一個(gè)前臺(tái)服務(wù)(API>18會(huì)有正在運(yùn)行通知欄)
3.廣播拉活
4.Service 拉活
5.JobScheduler 定時(shí)任務(wù)拉活
6.雙進(jìn)程拉活
網(wǎng)絡(luò)優(yōu)化及檢測(cè)
速度:1.GZIP 壓縮(okhttp 自動(dòng)支持);2.Protocol Buffer 替代 json;3.優(yōu)化圖片/文件流量;4.IP 直連省去 DNS 解析時(shí)間
成功率:1.失敗重試策略;
流量:1.GZIP 壓縮(okhttp 自動(dòng)支持);2.Protocol Buffer 替代 json;3.優(yōu)化圖片/文件流量;5.文件下載斷點(diǎn)續(xù)傳 ;6.緩存
協(xié)議層的優(yōu)化,比如更優(yōu)的 http 版本等
監(jiān)控:Charles 抓包、Network Monitor 監(jiān)控流量
UI卡頓優(yōu)化
減少布局層級(jí)及控件復(fù)雜度,避免過(guò)度繪制
使用 include、merge、viewstub
優(yōu)化繪制過(guò)程,避免在 Draw 中頻繁創(chuàng)建對(duì)象、做耗時(shí)操作
內(nèi)存泄漏場(chǎng)景及規(guī)避
1.靜態(tài)變量、單例強(qiáng)引跟生命周期相關(guān)的數(shù)據(jù)或資源,包括 EventBus
2.游標(biāo)、IO 流等資源忘記主動(dòng)釋放
3.界面相關(guān)動(dòng)畫(huà)在界面銷(xiāo)毀時(shí)及時(shí)暫停
4.內(nèi)部類(lèi)持有外部類(lèi)引用導(dǎo)致的內(nèi)存泄漏
handler 內(nèi)部類(lèi)內(nèi)存泄漏規(guī)避:1.使用靜態(tài)內(nèi)部類(lèi)+弱引用 2.界面銷(xiāo)毀時(shí)清空消息隊(duì)列
檢測(cè):Android Studio Profiler
LeakCanary 原理
通過(guò)弱引用和引用隊(duì)列監(jiān)控對(duì)象是否被回收
比如 Activity 銷(xiāo)毀時(shí)開(kāi)始監(jiān)控此對(duì)象,檢測(cè)到未被回收則主動(dòng) gc ,然后繼續(xù)監(jiān)控
OOM 場(chǎng)景及規(guī)避
加載大圖:減小圖片
內(nèi)存泄漏:規(guī)避內(nèi)存泄漏
5、Android 模塊化&熱修復(fù)&熱更新&打包&混淆&壓縮
Dalvik 和 ART
Dalvik
谷歌設(shè)計(jì)專(zhuān)用于 Android 平臺(tái)的 Java 虛擬機(jī),可直接運(yùn)行 .dex 文件,適合內(nèi)存和處理速度有限的系統(tǒng)
JVM 指令集是基于棧的;Dalvik 指令集是基于寄存器的,代碼執(zhí)行效率更優(yōu)
ART
Dalvik 每次運(yùn)行都要將字節(jié)碼轉(zhuǎn)換成機(jī)器碼;ART 在應(yīng)用安裝時(shí)就會(huì)轉(zhuǎn)換成機(jī)器碼,執(zhí)行速度更快
ART 存儲(chǔ)機(jī)器碼占用空間更大,空間換時(shí)間
APK 打包流程
1.aapt 打包資源文件生成 R.java 文件;aidl 生成 java 文件
2.將 java 文件編譯為 class 文件
3.將工程及第三方的 class 文件轉(zhuǎn)換成 dex 文件
4.將 dex 文件、so、編譯過(guò)的資源、原始資源等打包成 apk 文件
5.簽名
6.資源文件對(duì)齊,減少運(yùn)行時(shí)內(nèi)存
App 安裝過(guò)程
首先要解壓 APK,資源、so等放到應(yīng)用目錄
Dalvik 會(huì)將 dex 處理成 ODEX ;ART 會(huì)將 dex 處理成 OAT;
OAT 包含 dex 和安裝時(shí)編譯的機(jī)器碼
組件化路由實(shí)現(xiàn)
ARoute:通過(guò) APT 解析 @Route 等注解,結(jié)合 JavaPoet 生成路由表,即路由與 Activity 的映射關(guān)系
6、音視頻&FFmpeg&播放器
FFmpeg
基于命令方式實(shí)現(xiàn)了一個(gè)音視頻編輯 App:
https://github.com/yhaolpz/FFmpegCmd
集成編譯了 AAC、MP3、H264 編碼器
播放器原理
視頻播放原理:(mp4、flv)-> 解封裝 -> (mp3/aac、h264/h265)-> 解碼 -> (pcm、yuv)-> 音視頻同步 -> 渲染播放
音視頻同步:
選擇參考時(shí)鐘源:音頻時(shí)間戳、視頻時(shí)間戳和外部時(shí)間三者選擇一個(gè)作為參考時(shí)鐘源(一般選擇音頻,因?yàn)槿藢?duì)音頻更敏感,ijk 默認(rèn)也是音頻)
通過(guò)等待或丟幀將視頻流與參考時(shí)鐘源對(duì)齊,實(shí)現(xiàn)同步
IjkPlayer 原理
集成了 MediaPlayer、ExoPlayer 和 IjkPlayer 三種實(shí)現(xiàn),其中 IjkPlayer 基于 FFmpeg 的 ffplay
音頻輸出方式:AudioTrack、OpenSL ES;視頻輸出方式:NativeWindow、OpenGL ES
03總結(jié)
Android架構(gòu)學(xué)習(xí)進(jìn)階是一條漫長(zhǎng)而艱苦的道路,不能靠一時(shí)激情,更不是熬幾天幾夜就能學(xué)好的,必須養(yǎng)成平時(shí)努力學(xué)習(xí)的習(xí)慣。所以:貴在堅(jiān)持!
總結(jié)
以上是生活随笔為你收集整理的字节跳动资深面试官亲述:面试应该注意哪些问题?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: IE:免去脱机浏览中的麻烦(转)
- 下一篇: 优秀实践采购团队的8个要点