Android 面試點(diǎn)梳理

原文地址:https://juejin.cn/post/6844904190314037255

最新 Android 面試點(diǎn)梳理

目錄:

  • 網(wǎng)絡(luò):分層模型榔幸、TCP闹司、UDP税课、HTTP、HTTPS
  • 算法:數(shù)據(jù)結(jié)構(gòu)儡首、常用算法
  • Java 基礎(chǔ):StringBuilder、泛型擦除、Exception恋拍、IO隧土、容器
  • Java 同步:volatile提针、wait命爬、synchronized曹傀、可重入鎖、樂觀鎖饲宛、死鎖
  • Java 設(shè)計(jì)模式:六大原則皆愉、23 種設(shè)計(jì)模式、動(dòng)態(tài)代理
  • Java 虛擬機(jī):內(nèi)存模型艇抠、內(nèi)存結(jié)構(gòu)幕庐、GC、四種引用家淤、ClassLoader
  • Android 基礎(chǔ):Activity异剥、View 繪制、動(dòng)畫絮重、Window冤寿、SurfaceView、事件分發(fā)
  • Android 通信:Handler青伤、Parcelable督怜、IPC、Binder
  • Android 系統(tǒng):系統(tǒng)架構(gòu)狠角、Dalvik号杠、ART、系統(tǒng)啟動(dòng)丰歌、類加載器姨蟋、Apk 打包、Apk 安裝
  • Android 優(yōu)化:網(wǎng)絡(luò)優(yōu)化立帖、卡頓優(yōu)化芬探、內(nèi)存優(yōu)化、瘦包厘惦、內(nèi)存泄漏偷仿、ANR、Native Crash
  • 其他:解析 XML宵蕉、進(jìn)程痹途玻活、播放器羡玛、Lint别智、CI、CD稼稿、AOP薄榛、JetPack

網(wǎng)絡(luò):分層模型讳窟、TCP、UDP敞恋、HTTP丽啡、HTTPS

分層模型

  • 應(yīng)用層:負(fù)責(zé)處理特定的應(yīng)用程序細(xì)節(jié),如 HTTP硬猫、FTP补箍、DNS
  • 運(yùn)輸層:為兩臺(tái)主機(jī)提供端到端的基礎(chǔ)通信,如 TCP啸蜜、UDP
  • 網(wǎng)絡(luò)層:控制分組傳輸坑雅、路由選擇等,如 IP
  • 鏈路層:操作系統(tǒng)設(shè)備驅(qū)動(dòng)程序衬横、網(wǎng)卡相關(guān)接口

UDP

  • UDP 頭結(jié)構(gòu):來源端口裹粤、目的端口、長(zhǎng)度域蜂林、校驗(yàn)和
  • 特點(diǎn):不可靠遥诉、無序、面向報(bào)文悉尾、速度快突那、輕量
  • 適用場(chǎng)景:適用于即時(shí)通訊、視頻通話等
  • 應(yīng)用:DHCP构眯、DNS愕难、QUCI、VXLAN惫霸、GTP-U猫缭、TFTP、SNMP

TCP

  • TCP 頭結(jié)構(gòu):來源端口壹店、目的端口猜丹、序號(hào)、確認(rèn)序號(hào)硅卢、SYN/ACK 等狀態(tài)位射窒、窗口大小、校驗(yàn)和将塑、緊急指針
  • 特點(diǎn):面向字節(jié)流脉顿、有擁塞和流量控制、可靠点寥、有序艾疟、速度慢、較重量,通過滑動(dòng)窗口實(shí)現(xiàn)流量控制蔽莱、用塞控制
  • 適用場(chǎng)景:文件傳輸弟疆、瀏覽器等
  • 應(yīng)用:HTTP、HTTPS盗冷、RTMP怠苔、FTP、SMTP正塌、POP3
  • 三次握手:
1\. C->S:SYN嘀略,seq=x(你能聽到嗎恤溶?)
2\. S->C:SYN乓诽,seq=y,ack=x+1(我能聽到咒程,你能聽到嗎鸠天?)
3\. C->S:ACK,seq=x+1帐姻,ack=y+1(我能聽到稠集,開始吧)

兩方都要能確保:我說的話,你能聽到饥瓷;你說的話剥纷,我能聽到。所以需要三次握手
復(fù)制代碼
  • 四次揮手:
1\. C->S:FIN呢铆,seq=p(我說完了)
2\. S->C:ACK晦鞋,ack=p+1(我知道了,等一下棺克,我可能還沒說完)
3\. S->C:FIN悠垛,seq=q,ACK娜谊,ack=p+1(我也說完了)
4\. C->S:ACK确买,ack=q+1(我知道了,結(jié)束吧)

S 收到 C 結(jié)束的消息后 S 可能還沒說完纱皆,沒法立即回復(fù)結(jié)束標(biāo)示湾趾,只能等說完后再告訴 C :我說完了
復(fù)制代碼

HTTP

  • 超文本傳輸協(xié)議,明文傳輸派草,默認(rèn) 80 端口
  • POST 和 GET:Get 參數(shù)放在 url 中搀缠;Post 參數(shù)放在 request Body 中
  • 訪問網(wǎng)頁(yè)過程:DNS 域名解析、TCP 三次握手建立連接澳眷、發(fā)起 HTTP 請(qǐng)求

HTTPS

  • 默認(rèn) 443 端口胡嘿,使用 SSL 協(xié)議對(duì) HTTP 傳輸數(shù)據(jù)進(jìn)行了加密,安全
  • 加密過程:Client/Server 通過非對(duì)稱加密生成密鑰钳踊,然后用這個(gè)密鑰去對(duì)稱加密傳輸數(shù)據(jù)

算法:數(shù)據(jù)結(jié)構(gòu)衷敌、常用算法

數(shù)據(jù)結(jié)構(gòu)

  • 數(shù)組勿侯、鏈表
  • 棧、隊(duì)列
  • 散列表
  • 樹缴罗、堆助琐、圖

常用算法

  • 排序
  • 雙指針、滑動(dòng)窗口面氓、字符串
  • 遞歸兵钮、分治、二分
  • 回溯舌界、貪心掘譬、動(dòng)態(tài)規(guī)劃

Java 基礎(chǔ):StringBuilder、泛型擦除呻拌、Exception葱轩、IO、容器

StringBuilder

  • StringBuffer 線程安全藐握,StringBuilder 線程不安全
  • +實(shí)際上是用 StringBuilder 來實(shí)現(xiàn)的靴拱,所以非循環(huán)體可以直接用 +,循環(huán)體不行猾普,因?yàn)闀?huì)頻繁創(chuàng)建 StringBuilder
  • String.concat 實(shí)質(zhì)是 new String 袜炕,效率也低,耗時(shí)排序:StringBuilder < StringBuffer < concat < +

泛型擦除

  • 修飾成員變量等類結(jié)構(gòu)相關(guān)的泛型不會(huì)被擦除
  • 容器類泛型會(huì)被擦除

Exception 和 Error

  • Exception 和 Error 都繼承自 Throwable
  • Error 大部分是指不可恢復(fù)的錯(cuò)誤狀態(tài)初家,比如 OOM偎窘,所以也不需要捕獲
  • Exception 分為 CheckedException 和 UnCheckedException
    • CheckedException:必須顯式捕獲,受編譯器檢查笤成,比如 io 操作
    • UnCheckedException:不用顯示捕獲评架,比如空指針、數(shù)組越界等

IO 炕泳、 NIO纵诞、 OKIO

  • IO 是面向流的,一次一個(gè)字節(jié)的處理培遵,NIO 是面向緩沖區(qū)的浙芙,一次產(chǎn)生或消費(fèi)一個(gè)數(shù)據(jù)塊
  • IO 是阻塞的,NIO 是非阻塞的
  • NIO 支持內(nèi)存映射方式
  • okio 相比 io 和 nio籽腕,api 更簡(jiǎn)單易用
  • okio 支持超時(shí)機(jī)制
  • okio 引入 ByteString 空間換時(shí)間提高性能
  • okio 采用 segment 機(jī)制進(jìn)行內(nèi)存共享嗡呼,節(jié)省 copy 時(shí)間消耗

ArrayList、LinkedList

  • ArrayList
    • 基于數(shù)組實(shí)現(xiàn)皇耗,查找快:o(1)南窗,增刪慢:o(n)
    • 初始容量為10,擴(kuò)容通過 System.arrayCopy 方法
  • LinkedList
    • 基于雙向鏈表實(shí)現(xiàn),查找慢:o(n)万伤,增刪快:o(1)
    • 封裝了隊(duì)列和棧的調(diào)用

HashMap 窒悔、HashTable、HashSet

  • HashMap(允許 key/value 為 null)

    • 基于數(shù)組和單向鏈表實(shí)現(xiàn)敌买,數(shù)組是 HashMap 的主體简珠;鏈表是為解決哈希沖突而存在的,存放的是key和value結(jié)合的實(shí)體
    • 數(shù)組索引通過 key.hashCode(還會(huì)二次 hash) 得到虹钮,在鏈表上通過 key.equals 索引
    • 哈希沖突落在同一個(gè)桶中時(shí)聋庵,直接放在鏈表頭部(java1.8后放到尾部)
    • JAVA 8 中鏈表數(shù)量大于 8 時(shí)會(huì)轉(zhuǎn)為紅黑樹存儲(chǔ),查找時(shí)間由 O(n) 變?yōu)?O(logn)
    • 數(shù)組長(zhǎng)度總是2的n次方:這樣就能通過位運(yùn)算實(shí)現(xiàn)取余芙粱,從而讓 index 能落在數(shù)組長(zhǎng)度范圍內(nèi)
    • 加載因子(默認(rèn)0.75)表示添加到多少填充比時(shí)進(jìn)行擴(kuò)容祭玉,填充比大:鏈表較長(zhǎng),查找慢宅倒;填充比腥林妗:鏈表短屯耸,查找快
    • 擴(kuò)容時(shí)直接創(chuàng)建原數(shù)組兩倍的長(zhǎng)度拐迁,然后將原有對(duì)象再進(jìn)行hash找到新的index,重新放
  • HashTable(不允許 key/value 為 null)

    • 數(shù)據(jù)結(jié)構(gòu)和 HashMap 一樣
    • 線程安全
  • HashSet

    • 基于 HashMap 實(shí)現(xiàn)疗绣,元素就是 HashMap 的 key线召,Value 傳入了一個(gè)固定值

ArrayMap、SparseArray

  • ArrayMap

    • 基于兩個(gè)數(shù)組實(shí)現(xiàn)多矮,一個(gè)存放 hash缓淹;一個(gè)存放鍵值對(duì)
    • 存放 hash 的數(shù)組是有序的,查找時(shí)使用二分法查找
    • 發(fā)生哈希沖突時(shí)鍵值對(duì)數(shù)組里連續(xù)存放塔逃,查找時(shí)也是通過 key.equals索引讯壶,找不到時(shí)先向后再向前遍歷相同hash值的鍵值對(duì)數(shù)組
    • 擴(kuò)容時(shí)不像 HashMap 直接 double,內(nèi)存利用率高湾盗;也不需要重建哈希表伏蚊,只需要調(diào)用 system.arraycopy 數(shù)組拷貝,性能較高
    • 不適合存大量數(shù)據(jù)(1000以下)格粪,因?yàn)閿?shù)據(jù)量大的時(shí)候二分查找相比紅黑樹會(huì)慢很多
  • SparseArray

    • 基于 ArrayMap躏吊,key 只能是特定類型

Concurrent 集合

  • ConcurrentHashMap
    • 數(shù)據(jù)結(jié)構(gòu)跟 HashMap 一樣,還是數(shù)組加鏈表
    • 采用 segment 分段鎖技術(shù)帐萎,不像 HashTable 無腦直接同步 put 和 get 操作
    • get 操作沒有加鎖比伏,因?yàn)?value 用 volatile 修飾來保證可見行,性能很高
    • java1.8 后去除分段鎖疆导,采用 CAS 樂觀鎖加 synchronized 來實(shí)現(xiàn)

LRUCache 原理

  • 基于訪問順序排序的 LinkedHashMap 實(shí)現(xiàn)赁项,最近訪問的會(huì)排在最后

Java 同步:volatile、wait、synchronized悠菜、可重入鎖紫新、樂觀鎖、死鎖

volatile 關(guān)鍵字

  • 只能用來修飾變量李剖,適用修飾可能被多線程同時(shí)訪問的變量
  • 相當(dāng)于輕量級(jí)的 synchronized芒率,volatitle 能保證有序性(禁用指令重排序)、可見性
  • 變量位于主內(nèi)存中篙顺,每個(gè)線程還有自己的工作內(nèi)存偶芍,變量在自己線程的工作內(nèi)存中有份拷貝,線程直接操作的是這個(gè)拷貝
  • 被 volatile 修飾的變量改變后會(huì)立即同步到主內(nèi)存德玫,保持變量的可見性
  • 雙重檢查單例匪蟀,為什么要加 violate?
    • volatile想要解決的問題是宰僧,在另一個(gè)線程中想要使用instance材彪,發(fā)現(xiàn)instance!=null,但是實(shí)際上instance還未初始化完畢這個(gè)問題琴儿。將instance = newInstance();拆分為3句話是段化。1.分配內(nèi)存2.初始化3.將instance指向分配的內(nèi)存空間,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ì)釋放共享資源鎖

wait鼓鲁、notify蕴轨、notifyAll

  • 鎖池:某個(gè)對(duì)象的鎖已被線程A擁有,其他線程要執(zhí)行該對(duì)象的 synchronized 方法獲取鎖時(shí)就會(huì)進(jìn)入該對(duì)象的鎖池骇吭,鎖池中的線程回去競(jìng)爭(zhēng)該對(duì)象的鎖
  • 等待池:某個(gè)線程調(diào)用了某個(gè)對(duì)象的 wait 方法橙弱,該線程就會(huì)釋放該對(duì)象的鎖,進(jìn)入該對(duì)象的等待池绵跷,等待池中的線程不會(huì)去競(jìng)爭(zhēng)該對(duì)象的鎖
  • 調(diào)用 notify 會(huì)隨機(jī)喚醒等待池中的一個(gè)線程膘螟,喚醒后會(huì)進(jìn)入到鎖池
  • 調(diào)用 notifyAll 會(huì)喚醒等待池中的所有線程,喚醒后會(huì)都進(jìn)入到鎖池

lock 和 synchronized

  • synchronized 是 Java 關(guān)鍵字碾局,內(nèi)置特性荆残;Lock 是一個(gè)接口
  • synchronized 會(huì)自動(dòng)釋放鎖;lock 需要手動(dòng)釋放净当,所以需要寫到 try catch 塊中并在 finally 中釋放鎖
  • synchronized 無法中斷等待鎖内斯;lock 可以中斷
  • Lock 可以提高多個(gè)線程進(jìn)行讀/寫操作的效率
  • 競(jìng)爭(zhēng)資源激烈時(shí)蕴潦,lock 的性能會(huì)明顯的優(yōu)于 synchronized

Synchronized 原理

  • 每個(gè)對(duì)象都有一個(gè)監(jiān)視器鎖:monitor,同步代碼塊會(huì)執(zhí)行 monitorenter 開始俘闯,motnitorexit 結(jié)束
  • Wait/notify 就依賴 monitor 監(jiān)視器潭苞,所以在非同步代碼塊中執(zhí)行會(huì)報(bào) IllegalMonitorStateException 異常

可重入鎖

  • 定義:已經(jīng)獲取到鎖后,再次調(diào)用同步代碼塊/嘗試獲取鎖時(shí)不必重新去申請(qǐng)鎖真朗,可以直接執(zhí)行相關(guān)代碼
  • ReentrantLock 和 synchronized 都是可重入鎖

公平鎖

  • 定義:等待時(shí)間最久的線程會(huì)優(yōu)先獲得鎖
  • 非公平鎖無法保證哪個(gè)線程獲取到鎖此疹,synchronized 就是非公平鎖
  • ReentrantLock 默認(rèn)時(shí)非公平鎖,可以設(shè)置為公平鎖

樂觀鎖和悲觀鎖

  • 悲觀鎖:線程一旦得到鎖遮婶,其他線程就掛起等待蝗碎,適用于寫入操作頻繁的場(chǎng)景;synchronized 就是悲觀鎖
  • 樂觀鎖:假設(shè)沒有沖突旗扑,不加鎖蹦骑,更新數(shù)據(jù)時(shí)判斷該數(shù)據(jù)是否過期,過期的話則不進(jìn)行數(shù)據(jù)更新臀防,適用于讀取操作頻繁的場(chǎng)景
  • 樂觀鎖 CAS:Compare And Swap眠菇,更新數(shù)據(jù)時(shí)先比較原值是否相等,不相等則表示數(shù)據(jù)過去袱衷,不進(jìn)行數(shù)據(jù)更新
  • 樂觀鎖實(shí)現(xiàn):AtomicInteger捎废、AtomicLong、AtomicBoolean

死鎖 4 個(gè)必要條件

  • 互斥
  • 占有且等待
  • 不可搶占
  • 循環(huán)等待

Java 設(shè)計(jì)模式:六大原則祟昭、23 種設(shè)計(jì)模式缕坎、動(dòng)態(tài)代理

六大原則

  • 開閉原則:對(duì)拓展開放,對(duì)修改關(guān)閉
  • 單一指責(zé)原則:一個(gè)類指責(zé)單一
  • 里氏替換原則:引用基類的地方都能替換成子類對(duì)象
  • 依賴倒置原則:高層次模塊不依賴低層次模塊的具體實(shí)現(xiàn)篡悟,抽象不應(yīng)該依賴細(xì)節(jié)
  • 接口隔離原則:類之間的依賴關(guān)系應(yīng)該建立在最小的接口上
  • 迪米特原則:一個(gè)對(duì)象對(duì)其他對(duì)象應(yīng)該有盡量少的了解

Java 23 種設(shè)計(jì)模式(按目的分類為:5+7+11)

1995 年 GoF(四人組)出了一本設(shè)計(jì)模式的書,收錄了 23 種設(shè)計(jì)模式匾寝,樹立設(shè)計(jì)模式里程碑搬葬,也叫:GoF 設(shè)計(jì)模式

  • 創(chuàng)建型(5):描述怎么創(chuàng)建對(duì)象
    • 1.單例模式
    • 2.原型模式:對(duì)象的拷貝
    • 3.建造者模式
    • 4.工廠模式:建立一個(gè)工廠方法來制造新的對(duì)象
    • 5.抽象工廠模式:
  • 結(jié)構(gòu)型(7):描述如何將類或?qū)ο蟀茨撤N規(guī)則組成更大的結(jié)構(gòu)
    • 1.橋接模式:對(duì)于兩個(gè)或以上緯度獨(dú)立變化的場(chǎng)景,將抽象與具體實(shí)現(xiàn)分離艳悔,實(shí)例:用不同顏色畫不同形狀
    • 2.外觀模式:對(duì)外有一個(gè)統(tǒng)一接口急凰,外部不用關(guān)心內(nèi)部子系統(tǒng)的具體實(shí)現(xiàn),這是"迪米特原則"的典型應(yīng)用
    • 3.適配器模式:改變類的接口猜年,使原本由于接口不匹配而無法一起工作的兩個(gè)類能夠在一工作抡锈,實(shí)例:RecycleView 的 Adapter 不管什么類型的 View 都返回 ViewHolder
    • 4.代理模式:由代理對(duì)象控制對(duì)原對(duì)象的引用,包括靜態(tài)代理和動(dòng)態(tài)代理
    • 5.組合模式:將對(duì)象組成樹形結(jié)構(gòu)乔外,用于對(duì)單個(gè)對(duì)象和組合對(duì)象的使用具有一致性床三,實(shí)例:ViewGroup
    • 6.裝飾模式:對(duì)對(duì)象包裝一層,動(dòng)態(tài)的增加一些額外功能杨幼,實(shí)例:ContextWrapper 包裝 Context
    • 7.享元模式:復(fù)用對(duì)象撇簿,實(shí)例:java 的常量池(比如 String)聂渊,線程池,Message.obtain 等
  • 行為型(11):描述類或?qū)ο笾g怎么相互協(xié)作四瘫,怎樣分配指責(zé)
    • 1.觀察者模式:一對(duì)多依賴關(guān)系汉嗽,多個(gè)觀察者可以同時(shí)監(jiān)聽某一個(gè)對(duì)象,實(shí)例:jetpack 的 lifeCycle 添加生命周期觀察者
    • 2.中介者模式:定義一個(gè)中介對(duì)象封裝一系列對(duì)象的交互找蜜,解耦這些對(duì)象饼暑,實(shí)例:MVP 的 P
    • 3.訪問者模式:將作用于某數(shù)據(jù)結(jié)構(gòu)中各元素的操作分離出來封裝成獨(dú)立的類,對(duì)這些元素添加新的操作洗做,但不改變?cè)瓟?shù)據(jù)結(jié)構(gòu)撵孤,實(shí)例:asm 中的 classVisitor 中再分別對(duì)類注解、變量、方法等進(jìn)行處理
    • 4.狀態(tài)模式:行為由狀態(tài)決定,不同狀態(tài)下由不同行為硫兰,與策略模式類似萧福,實(shí)例:不同狀態(tài)下有同一種操作的不同行為的子類實(shí)現(xiàn)
    • 5.命令模式:將一個(gè)請(qǐng)求封裝為一個(gè)對(duì)象發(fā)出,交給別的對(duì)象去處理請(qǐng)求煌贴,實(shí)例:Handler 發(fā)送定義好的消息事件
    • 6.策略模式:將一系列的算法封裝起來,方便替換,實(shí)例:動(dòng)畫的時(shí)間插值器
    • 7.責(zé)任鏈模式:讓多個(gè)對(duì)象都有機(jī)會(huì)處理一個(gè)事件影钉,實(shí)例:View 事件傳遞機(jī)制
    • 8.備忘錄模式:保存對(duì)象之前的狀態(tài),方便后面恢復(fù)
    • 9.迭代器模式:提供一種方法遍歷容器中的元素掘剪,而不需要暴露該對(duì)象的內(nèi)部表示平委,實(shí)例:集合的迭代器
    • 10.解釋器模式:多次出現(xiàn)的問題有一定規(guī)律,就可以歸納成一種簡(jiǎn)單的語(yǔ)言來解釋夺谁,實(shí)例:AndroidManifest 文件廉赔、GLES 著色器語(yǔ)言
    • 11.模版方法模式:定義一套固定步驟,方便直接執(zhí)行匾鸥,實(shí)例:AsyncTask

動(dòng)態(tài)代理原理及實(shí)現(xiàn)

  • InvocationHandler 接口蜡塌,動(dòng)態(tài)代理類需要實(shí)現(xiàn)這個(gè)接口
  • Proxy.newProxyInstance,用于動(dòng)態(tài)創(chuàng)建代理對(duì)象
  • Retrofit 應(yīng)用: Retrofit 通過動(dòng)態(tài)代理勿负,為我們定義的請(qǐng)求接口都生成一個(gè)動(dòng)態(tài)代理對(duì)象馏艾,實(shí)現(xiàn)請(qǐng)求

JVM:內(nèi)存模型、內(nèi)存結(jié)構(gòu)奴愉、GC琅摩、四種引用、ClassLoader

JVM

  • 定義:可以理解成一個(gè)虛構(gòu)的計(jì)算機(jī)锭硼,解釋自己的字節(jié)碼指令集映射到本地 CPU 或 OS 的指令集房资,上層只需關(guān)注 Class 文件,與操作系統(tǒng)無關(guān)账忘,實(shí)現(xiàn)跨平臺(tái)
  • Kotlin 就是能解釋成 Class 文件志膀,所以可以跑在 JVM 上

JVM 內(nèi)存模型

  • Java 多線程之間是通過共享內(nèi)存來通信的熙宇,每個(gè)線程都有自己的本地內(nèi)存
  • 共享變量存放于主內(nèi)存中,線程會(huì)拷貝一份共享變量到本地內(nèi)存
  • volatile 關(guān)鍵字就是給內(nèi)存模型服務(wù)的溉浙,用來保證內(nèi)存可見性和順序性

JVM 內(nèi)存結(jié)構(gòu)

  • 線程私有:
    • 1.程序計(jì)數(shù)器:記錄正在執(zhí)行的字節(jié)碼指令地址烫止,若正在執(zhí)行 Native 方法則為空
    • 2.虛擬機(jī)棧:執(zhí)行方法時(shí)把方法所需數(shù)據(jù)存為一個(gè)棧幀入棧,執(zhí)行完后出棧
    • 3.本地方法棧:同虛擬機(jī)棧戳稽,但是針對(duì)的是 Native 方法
  • 線程共享:
    • 1.堆:存儲(chǔ) Java 實(shí)例馆蠕,GC 主要區(qū)域,分代收集 GC 方法會(huì)吧堆劃分為新生代惊奇、老年代
    • 2.方法區(qū):存儲(chǔ)類信息互躬,常量池,靜態(tài)變量等數(shù)據(jù)

GC

  • 回收區(qū)域:只針對(duì)堆颂郎、方法區(qū)吼渡;線程私有區(qū)域數(shù)據(jù)會(huì)隨線程結(jié)束銷毀,不用回收
  • 回收類型:
    • 1.堆中的對(duì)象:分代收集 GC 方法會(huì)吧堆劃分為新生代乓序、老年代寺酪。 新生代:新建小對(duì)象會(huì)進(jìn)入新生代;通過復(fù)制算法回收對(duì)象替劈;老年代:新建大對(duì)象及老對(duì)象會(huì)進(jìn)入老年代寄雀;通過標(biāo)記-清除算法回收對(duì)象。
    • 2.方法區(qū)中的類信息陨献、常量池
  • 判斷一個(gè)對(duì)象是否可被回收:
    • 1.引用計(jì)數(shù)法:有循環(huán)引用的缺點(diǎn)
    • 2.可達(dá)性分析法:從 GC ROOT 開始搜索盒犹,不可達(dá)的對(duì)象都是可以被回收的。其中 GC ROOT 包括虛擬機(jī)棧/本地方法棧中引用的對(duì)象眨业、方法區(qū)中常量/靜態(tài)變量引用的對(duì)象急膀。

Minor GC/Major GC/Full GC

  • Minor GC(Young GC):即新生代(分為一個(gè) Eden 區(qū)和兩個(gè) Survivor 區(qū))的垃圾回收
    • Eden 區(qū)無用對(duì)象被回收,存活對(duì)象會(huì)移到 Survivor 區(qū)
    • Survivor 區(qū)的存活對(duì)象會(huì)被復(fù)制到另一個(gè) Survivor 區(qū)坛猪,復(fù)制次數(shù)也記做年齡脖阵,年齡足夠大時(shí)(15)會(huì)移到老年代
    • 如果 Survivor 區(qū)已滿,則存活對(duì)象會(huì)被提前移動(dòng)到老年代(過早提升)墅茉,如果老年代也無法容納,則會(huì)觸發(fā) Full GC(提升失斘啬拧)
    • 老年代的對(duì)象可能引用新生代對(duì)象就斤,所以這個(gè)引用會(huì)被作為 GC Roots
  • Major GC:通常是跟 Full GC 等價(jià)的,回收整個(gè)堆
  • Full GC:回收整個(gè)堆蘑辑,包括新生代和老年代
    • 當(dāng)要在老年代分配空間但無法容納時(shí)觸發(fā)
    • 當(dāng)主動(dòng)調(diào)用 System.gc 時(shí)觸發(fā)

四種引用

  • 強(qiáng)引用:不會(huì)被回收
  • 軟引用:內(nèi)存不足時(shí)會(huì)被回收
  • 弱引用:gc 時(shí)會(huì)被回收
  • 虛引用:無法通過虛引用得到對(duì)象洋机,可以監(jiān)聽對(duì)象的回收

ClassLoader

  • 類的生命周期: 1.加載;2.驗(yàn)證洋魂;3.準(zhǔn)備绷旗;4.解析喜鼓;5.初始化;6.使用衔肢;7.卸載
  • 類加載過程: 1.加載:獲取類的二進(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)塊代碼角骤、類變量賦值
  • 類加載時(shí)機(jī): 1.實(shí)例化對(duì)象 2.調(diào)用類的靜態(tài)方法 3.調(diào)用類的靜態(tài)變量(放入常量池的常量除外)
  • 類加載器:負(fù)責(zé)加載 class 文件 1.引導(dǎo)類加載器 - 沒有父類加載器 2.拓展類加載器 - 繼承自引導(dǎo)類加載器 3.系統(tǒng)類加載器 - 繼承自拓展類加載器
  • 雙親委托模型:
    • 當(dāng)要加載一個(gè) class 時(shí)隅忿,會(huì)先逐層向上讓父加載器先加載,加載失敗才會(huì)自己加載
    • 為什么叫雙親邦尊?不考慮自定義加載器背桐,系統(tǒng)類加載器需要網(wǎng)上詢問兩層,所以叫雙親
    • 判斷是否是同一個(gè)類時(shí)蝉揍,除了類信息链峭,還必須時(shí)同一個(gè)類加載器
    • 優(yōu)點(diǎn):防止重復(fù)加載,父加載器加載過了就沒必要加載了又沾;安全弊仪,防止篡改核心庫(kù)類

Android 基礎(chǔ):Activity、View 繪制捍掺、動(dòng)畫撼短、Window、SurfaceView挺勿、事件分發(fā)

Activity 生命周期

  • A 打開 B 界面曲横,會(huì)先執(zhí)行 A 的 onPause,再執(zhí)行 B 的 onCreate不瓶、onStart禾嫉、onResume,再執(zhí)行 A 的 onStop
  • B 界面的打開依賴 A 界面 onPause 方法執(zhí)行完蚊丐,所以不要在 onPause 中做耗時(shí)操作

Activity 啟動(dòng)模式

  • standard 標(biāo)準(zhǔn)模式
  • singleTop 棧頂復(fù)用模式熙参,適用于推送點(diǎn)擊消息界面
  • singleTask 棧內(nèi)復(fù)用模式,適用于 App 首頁(yè)
  • singleInstance 單例模式麦备,單獨(dú)位于一個(gè)任務(wù)棧中孽椰,適用于撥打電話界面
  • 細(xì)節(jié):
    • taskAffinity:任務(wù)相關(guān)性,用于指定任務(wù)棧名稱凛篙,默認(rèn)為應(yīng)用包名
    • allowTaskReparenting:允許轉(zhuǎn)移任務(wù)棧

View 工作原理

  • ViewRoot 的 performTraversals 方法調(diào)用觸發(fā)開始 View 的繪制黍匾,然后會(huì)依次調(diào)用:
    • performMeasure:遍歷 View 的 measure 測(cè)量尺寸
    • performLayout:遍歷 View 的 layout 確定位置
    • performDraw:遍歷 View 的 draw 繪制

MeasureSpec 測(cè)量規(guī)則

  • EXACTLY:父 View 指定了子 View 確切的大小
  • AT_MOST:父 View 指定一個(gè)大小,子 View 不能超過這個(gè)值
  • UNSPECIFIEND: 父 View 不對(duì)子 View 有任何限制

View 動(dòng)畫呛梆、幀動(dòng)畫及屬性動(dòng)畫

  • View 動(dòng)畫:
    • 作用對(duì)象是 View锐涯,可用 xml 定義,建議 xml 實(shí)現(xiàn)比較易讀
    • 支持四種效果:平移填物、縮放纹腌、旋轉(zhuǎn)霎终、透明度
  • 幀動(dòng)畫:
    • 通過 AnimationDrawable 實(shí)現(xiàn),容易 OOM
  • 屬性動(dòng)畫:
    • 可作用于任何對(duì)象升薯,可用 xml 定義莱褒,Android 3 引入,建議代碼實(shí)現(xiàn)比較靈活
    • 包括 ObjectAnimator覆劈、ValuetAnimator保礼、AnimatorSet
    • 時(shí)間插值器:根據(jù)時(shí)間流逝的百分比計(jì)算當(dāng)前屬性改變的百分比,系統(tǒng)預(yù)置勻速责语、加速炮障、減速等插值器
    • 類型估值器:根據(jù)當(dāng)前屬性改變的百分比計(jì)算改變后的屬性值,系統(tǒng)預(yù)置整型坤候、浮點(diǎn)胁赢、色值等類型估值器
    • 使用注意事項(xiàng):避免使用幀動(dòng)畫,容易OOM白筹;界面銷毀時(shí)停止動(dòng)畫智末,避免內(nèi)存泄漏;開啟硬件加速徒河,提高動(dòng)畫流暢性
    • 硬件加速原理:將 cpu 一部分工作分擔(dān)給 gpu 系馆,使用 gpu 完成繪制工作;從工作分?jǐn)偤屠L制機(jī)制兩個(gè)方面優(yōu)化了繪制速度

Window 顽照、WindowManager由蘑、WMS、SurfaceFlinger

  • WIndow:抽象概念不是實(shí)際存在的代兵,而是以 View 的形式存在尼酿,通過 PhoneWindow 實(shí)現(xiàn)
  • WindowManager:外界訪問 Window 的入口,內(nèi)部與 WMS 交互是個(gè) IPC 過程
  • WMS:管理窗口 Surface 的布局和次序植影,作為系統(tǒng)級(jí)服務(wù)單獨(dú)運(yùn)行在一個(gè)進(jìn)程
  • SurfaceFlinger:將 WMS 維護(hù)的窗口按一定次序混合后顯示到屏幕上

SurfaceView裳擎、TextureView、SurfaceTexture思币、GLSurfaceView

  • SurfaceView:使用雙緩沖機(jī)制鹿响,有自己的 surface,在一個(gè)獨(dú)立的線程里繪制谷饿,Android7.0之前不能平移抢野、縮放
  • TextureView:持有 SurfaceTexture,將圖像處理為 OpenGL 紋理更新到 HardwareLayer各墨,必須開啟硬件加速,Android5.0之前在主線程渲染启涯,之后有獨(dú)立的渲染線程贬堵,可以平移恃轩、旋轉(zhuǎn)、縮放
  • SurfaceTexture:將圖像流轉(zhuǎn)為 OpenGL 外部紋理黎做,不直接顯示
  • GLSurfaceView:加入 EGL 管理叉跛,自帶 GL 上下文和 GL 渲染線程

事件分發(fā)機(jī)制

  • 一個(gè) MotionEvent 產(chǎn)生后,按 Activity -> Window -> decorView -> View 順序傳遞蒸殿,View 傳遞過程就是事件分發(fā)筷厘,主要依賴三個(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 沒有 onIntercept 方法,直接調(diào)用 onTouchEvent 處理
    • OnTouchListener 優(yōu)先級(jí)比 OnTouchEvent 高霞玄,onClickListener 優(yōu)先級(jí)最低
    • requestDisallowInterceptTouchEvent 可以屏蔽父容器 onIntercept 方法的調(diào)用

Android 通信:Handler骤铃、Parcelable、IPC坷剧、Binder

Handler惰爬、MessageQueue、Looper 及 postDelayed 原理

  • Handler:開發(fā)直接接觸的類惫企,內(nèi)部持有 MessageQueue 和 Looper
  • MessageQueue:消息隊(duì)列撕瞧,內(nèi)部通過單鏈表存儲(chǔ)消息
  • Looper:內(nèi)部持有 MessageQueue,循環(huán)查看是否有新消息雅任,有就處理风范,沒就阻塞
  • postDelayed 其實(shí)就是調(diào)用 postAtTime 實(shí)現(xiàn)的,傳入的時(shí)間戳基于 SystemClock.uptimeMillis沪么,即 boot 時(shí)間
  • 進(jìn)一步會(huì)調(diào)用 MessageQueue#enqueueMessage 將消息插入到隊(duì)列
  • 插入消息時(shí)會(huì)根據(jù)消息執(zhí)行時(shí)刻 Message#when 來決定插入到什么位置硼婿,when 為 0 或最早執(zhí)行就會(huì)插入到鏈表頭,否則按執(zhí)行時(shí)刻排序插入
  • 插入后如果正在阻塞則會(huì)嘗試喚醒禽车,插入到頭部則會(huì)喚醒寇漫,插入到隊(duì)列中則再根據(jù)其他條件判斷是否需要喚醒
  • Looper#loop 中調(diào)用 MessageQueue#next 取消息,next 方法除非是即將銷毀時(shí)會(huì)返回 null殉摔,否則就會(huì)返回消息州胳,沒有消息就阻塞。如果當(dāng)前時(shí)刻還沒到消息的執(zhí)行時(shí)刻 when逸月,就會(huì)再阻塞這個(gè)時(shí)間差的時(shí)間
  • 阻塞是調(diào)用 nativePollOnce 實(shí)現(xiàn)栓撞,基于 Linux epoll 事件管理機(jī)制
  • Looper#loop 中取出消息后通過 Message#target 拿到 handler,然后調(diào)用 Handler#dispatchMessage 分發(fā)處理消息

Serializable、Parcelable

  • Serializable :Java 序列化方式瓤湘,適用于存儲(chǔ)和網(wǎng)絡(luò)傳輸瓢颅,serialVersionUID 用于確定反序列化和類版本是否一致,不一致時(shí)反序列化回失敗
  • Parcelable :Android 序列化方式弛说,適用于組件通信數(shù)據(jù)傳遞挽懦,性能高,因?yàn)椴幌?Serializable 一樣有大量反射操作

Linux IPC 方式

  • 管道
  • socket
  • 信號(hào)量:常作為一種鎖機(jī)制木人,防止某進(jìn)程正在訪問共享資源時(shí)信柿,其他進(jìn)程也訪問該資源。因此醒第,主要作為進(jìn)程間以及同一進(jìn)程內(nèi)不同線程之間的同步手段
  • 信號(hào):不適用于信息交換渔嚷,更適用于進(jìn)程中斷控制,比如非法內(nèi)存訪問淘讥,殺死某個(gè)進(jìn)程等(Android 中的 Kill Process 采用的就是 signal(信號(hào))機(jī)制)
  • 消息隊(duì)列:信息復(fù)制兩次圃伶,額外的 CPU 消耗;不合適頻繁或信息量大的通信
  • 共享內(nèi)存:無須復(fù)制蒲列,共享緩沖區(qū)直接付附加到進(jìn)程虛擬地址空間窒朋,速度快;但進(jìn)程間的同步問題操作系統(tǒng)無法實(shí)現(xiàn)蝗岖,必須各進(jìn)程利用同步工具解決

Binder

  • Android 中基于 C/S 結(jié)構(gòu)的一種面向?qū)ο蟮倪M(jìn)程間通信的機(jī)制
  • 主要用在 system_server 進(jìn)程與上層 App 層的 IPC 交互
  • 包含:Client,Server,Binder 驅(qū)動(dòng)和 ServiceManager 四部分

Android 為什么選擇 binder

  • 性能:使用 mmap 一次數(shù)據(jù)拷貝實(shí)現(xiàn) IPC侥猩,傳統(tǒng) IPC:用戶 A 空間->內(nèi)核->用戶 B 空間;mmap 將內(nèi)核與用戶 B 空間映射抵赢,實(shí)現(xiàn)直接從用戶 A 空間->用戶B空間欺劳,而 Linux 的管道、消息隊(duì)列铅鲤、Socket 都需要拷貝兩次划提,binder 僅次于共享內(nèi)存
  • 穩(wěn)定性:基于C/S架構(gòu),架構(gòu)清晰邢享,穩(wěn)定性好鹏往,不像共享內(nèi)存實(shí)現(xiàn)方式復(fù)雜,需要充分考慮訪問臨界資源的并發(fā)同步問題
  • 安全:傳統(tǒng)Linux IPC的接收方無法獲得對(duì)方進(jìn)程可靠的UID/PID骇塘,從而無法鑒別對(duì)方身份

Android 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ù)端:將暴漏給客戶端的接口聲明在 AIDL 文件中插爹,創(chuàng)建 Service 實(shí)現(xiàn) AIDL 接口并監(jiān)聽客戶端連接請(qǐng)求
    • 客戶端:綁定服務(wù)端 Service 哄辣,綁定成功后拿到服務(wù)端 Binder 對(duì)象轉(zhuǎn)為 AIDL 接口調(diào)用
    • RemoteCallbackList 實(shí)現(xiàn)跨進(jìn)程接口監(jiān)聽,同個(gè) Binder 對(duì)象做 key 存儲(chǔ)客戶端注冊(cè)的 listener
    • 監(jiān)聽 Binder 斷開: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):系統(tǒng)架構(gòu)超全、Dalvik、ART邓馒、系統(tǒng)啟動(dòng)嘶朱、類加載器、Apk 打包光酣、Apk 安裝

Android 系統(tǒng)架構(gòu)

[圖片上傳失敗...(image-52567d-1626161018037)]

<figcaption style="display: block;"></figcaption>

  • 應(yīng)用層
  • Framework 框架層
  • 本地 Native 庫(kù)和 Android 運(yùn)行時(shí)環(huán)境
  • HAL
  • Linux 內(nèi)核

Dalvik 和 ART

  • Dalvik
    • 谷歌設(shè)計(jì)專用于 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í)間

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)程開啟 AMS、WMS 等 -> 啟動(dòng) Launcher 應(yīng)用進(jìn)程

Android 類加載器

  • BootClassLoader(加載 Framework 級(jí)別的類)
  • PathClassLoader(加載系統(tǒng)類和 data/app 應(yīng)用目錄下的 dex 文件)
  • DexClassLoader(加載自定義的 dex 文件或 jar拷泽,支持從 sd 卡中進(jìn)行加載)

APK 打包流程

  • 1.aapt 打包資源文件生成 R.java 文件疫鹊;aidl 生成 java 文件
  • 2.將 java 文件編譯為 class 文件
  • 3.將工程及第三方的 class 文件轉(zhuǎn)換成 dex 文件
  • 4.將 dex 文件、so司致、編譯過的資源拆吆、原始資源等打包成 apk 文件
  • 5.簽名
  • 6.資源文件對(duì)齊,減少運(yùn)行時(shí)內(nèi)存

App 安裝過程

  • 首先要解壓 APK脂矫,資源枣耀、so等放到應(yīng)用目錄
  • Dalvik 會(huì)將 dex 處理成 ODEX ;ART 會(huì)將 dex 處理成 OAT羹唠;
  • OAT 包含 dex 和安裝時(shí)編譯的機(jī)器碼

Android 優(yōu)化:網(wǎng)絡(luò)優(yōu)化奕枢、卡頓優(yōu)化、內(nèi)存優(yōu)化佩微、瘦包缝彬、內(nèi)存泄漏、ANR哺眯、Native Crash

網(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ù)雜度荔茬,避免過度繪制
  • 使用 include、merge竹海、viewstub
  • 優(yōu)化繪制過程慕蔚,避免在 Draw 中頻繁創(chuàng)建對(duì)象、做耗時(shí)操作

內(nèi)存優(yōu)化

  • 內(nèi)存問題
    • 內(nèi)存泄漏
    • 內(nèi)存抖動(dòng):頻繁創(chuàng)建臨時(shí)對(duì)象
    • Bitmap 大內(nèi)存:規(guī)避位圖超標(biāo)
    • 代碼質(zhì)量:intdef 代替枚舉斋配,使用 SparseArray 代替 HashMap
  • 檢測(cè)工具
    • MAT(Memory Analysis Tools) 孔飒,可分析 Java 堆數(shù)據(jù),可查看實(shí)例占用空間艰争、引用關(guān)系等
    • Android Studio 自帶的 Profiler
    • LeakCanary:通過弱引用和引用隊(duì)列監(jiān)控對(duì)象是否被回收坏瞄,比如 Activity 銷毀時(shí)開始監(jiān)控此對(duì)象,檢測(cè)到未被回收則主動(dòng) gc 园细,然后繼續(xù)監(jiān)控

瘦包

  • 1.資源方面:資源在線化惦积、圖片使用 webp 格式、tint 著色生成不同色調(diào)的切猛频、使用 icon font
  • 2.so 庫(kù):保留一個(gè) cpu 架構(gòu)的 so 文件
  • 3.AS Inspect Code 清除無用代碼和資源
  • 4.代碼混淆:使用 ProGuard 可以移除無用的類狮崩、字段、方法(壓縮)鹿寻,移除無用字節(jié)碼指令
  • 5.不保留行號(hào):使用 ProGuard 配置不保留行號(hào)
  • 6.開啟 shrinkResources:移除無用資源
  • 7.資源混淆:使用 AndResGuard 縮短資源長(zhǎng)度睦柴,對(duì)資源進(jìn)行 7z 壓縮等(直接對(duì)apk操作)
  • 8.代碼結(jié)構(gòu)簡(jiǎn)化,比如用 intdef 代替 枚舉(一個(gè)枚舉有1~1.4kb大小)
  • 9.使用 compileOnly 在只需編譯時(shí)依賴的場(chǎng)景毡熏,不會(huì)打到 apk 里
  • 10.使用 thinR 插件剔除 R 文件坦敌,將引用 R 字段的地方替換成對(duì)應(yīng)常量
  • 11.Android 7.0 使用 V2(apksigner) 代替 V1(jarsigner) 簽名工具
  • 12.動(dòng)態(tài)加載 so 庫(kù)(System.load加載絕對(duì)路徑文件)、插件化技術(shù)痢法、App Bundle
  • 13.使用 facebook 的 redex

內(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)畫在界面銷毀時(shí)及時(shí)暫停
  • 4.內(nèi)部類持有外部類引用導(dǎo)致的內(nèi)存泄漏
    • handler 內(nèi)部類內(nèi)存泄漏規(guī)避:1.使用靜態(tài)內(nèi)部類+弱引用 2.界面銷毀時(shí)清空消息隊(duì)列
    • 檢測(cè):Android Studio Profiler

ANR 問題及分析

  • anr 分類
    • 主線程 5s 內(nèi)沒有處理完輸入事件
    • service 阻塞 20s
    • 前臺(tái)廣播阻塞 10s 或后臺(tái)廣告阻塞 20s
    • ContentProvider publish 在 20s 內(nèi)沒有處理完
  • anr 發(fā)生過程
    • 1.捕獲到 anr蘸炸,發(fā)送 linux 信號(hào)量 3
    • 2.進(jìn)程接受到信號(hào)量將 anr 信息寫入 data/anr/traces.txt 文件
    • 3.Log 打印 anr 信息
    • 4.進(jìn)程進(jìn)入 anr 狀態(tài),彈出 anr 提示框
  • 監(jiān)控 anr
    • 1.Android 5.0 以下監(jiān)聽 traces.txt 文件寫入
    • 2.每隔 5s 向主線程發(fā)送消息判斷主線程是否阻塞
  • 分析 anr
    • 查看 cpu 負(fù)載是否是 cpu 資源緊張導(dǎo)致
    • 查看堆椉獗迹看是否是我們的代碼耗時(shí)過長(zhǎng)
  • 避免 anr
    • 主線程中不要做耗時(shí)操作搭儒,注意使用 IntentService
    • 降低子線程優(yōu)先級(jí)穷当,讓主線程可以更多的獲取到 cpu 資源

Native Crash

  • 崩潰過程:native crash 時(shí)操作系統(tǒng)會(huì)向進(jìn)程發(fā)送信號(hào),崩潰信息會(huì)寫入到 data/tombstones 下淹禾,并在 logcat 輸出崩潰日志
  • 定位:so 庫(kù)剝離調(diào)試信息的話馁菜,只有相對(duì)位置沒有具體行號(hào),可以使用 NDK 提供的 addr2line 或 ndk-stack 來定位
  • addr2line:根據(jù)有調(diào)試信息的 so 和相對(duì)位置定位實(shí)際的代碼處
  • ndk-stack:可以分析 tombstone 文件铃岔,得到實(shí)際的代碼調(diào)用棧

其他:解析 XML汪疮、進(jìn)程保活德撬、播放器铲咨、Lint、CI蜓洪、CD、AOP坯苹、JetPack

Android 解析 XML

  • SAX:流式解析
  • DOM:先把 XML 全部讀取到內(nèi)存隆檀,再訪問樹形結(jié)構(gòu),很消耗內(nèi)存
  • PULL:流式解析粹湃,Android 內(nèi)置的默認(rèn)解析方式

熱修復(fù)恐仑、插件化、組件化

  • 熱修復(fù)原理:
    • Native Hook(AndFix):直接在 native 層進(jìn)行方法的結(jié)構(gòu)體信息對(duì)換
    • 分包(QFix):插入新 dex 到 dexElements[]为鳄,利用 ClassLoader 通過遍歷 dexElements[] 來 findClass 的特性
    • Java Hook(Robust):hook 每個(gè)方法裳仆,在每個(gè)方法里埋好準(zhǔn)備替換的邏輯
  • 插件化:DexClassLoader 動(dòng)態(tài)加載,四大組件未注冊(cè)問題通過 hook AMS孤钦、Instrumentation 等解決歧斟,VirtualAPK 源碼分析
  • 組件化:ARoute 路由實(shí)現(xiàn):通過 APT 解析 @Route 等注解,結(jié)合 JavaPoet 生成路由表偏形,即路由與 Activity 的映射關(guān)系

進(jìn)程本残洌活

  • 進(jìn)程優(yōu)先級(jí):1.前臺(tái)進(jìn)程 ;2.可見進(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)廠商省電機(jī)制殺死捐康;3.用戶主動(dòng)清理
  • 保活方式:
    • 1.Activity 提權(quán):掛一個(gè) 1像素 Activity 將進(jìn)程優(yōu)先級(jí)提高到前臺(tái)進(jìn)程
    • 2.Service 提權(quán):?jiǎn)?dòng)一個(gè)前臺(tái)服務(wù)(API>18會(huì)有正在運(yùn)行通知欄)
    • 3.廣播拉活
    • 4.Service 拉活
    • 5.JobScheduler 定時(shí)任務(wù)拉活
    • 6.雙進(jìn)程拉活

播放器原理

  • 視頻播放原理:(mp4庸蔼、flv)-> 解封裝 -> (mp3/aac解总、h264/h265)-> 解碼 -> (pcm、yuv)-> 音視頻同步 -> 渲染播放
  • 音視頻同步:
    • 選擇參考時(shí)鐘源:音頻時(shí)間戳朱嘴、視頻時(shí)間戳和外部時(shí)間三者選擇一個(gè)作為參考時(shí)鐘源(一般選擇音頻倾鲫,因?yàn)槿藢?duì)音頻更敏感粗合,ijk 默認(rèn)也是音頻)
    • 通過等待或丟幀將視頻流與參考時(shí)鐘源對(duì)齊,實(shí)現(xiàn)同步
  • IjkPlayer 原理
    • 集成了 MediaPlayer乌昔、ExoPlayer 和 IjkPlayer 三種實(shí)現(xiàn)隙疚,其中 IjkPlayer 基于 FFmpeg 的 ffplay
    • 音頻輸出方式:AudioTrack、OpenSL ES磕道;視頻輸出方式:NativeWindow供屉、OpenGL ES

Lint

  • Android Lint 是 Google 提供給 Android 開發(fā)者的靜態(tài)代碼檢查工具
  • 使用 Lint 對(duì) Android 工程代碼進(jìn)行掃描和檢查,可以發(fā)現(xiàn)代碼潛在的問題溺蕉,提醒程序員及早修正
  • 基于 Detector伶丐、IssueRegistry 實(shí)現(xiàn),通過 lintChecks project 引入

CI

  • Continuous integration(持續(xù)集成疯特,簡(jiǎn)稱CI):頻繁的將代碼集成到主干哗魂,防止分支大幅偏離主干,方便快速發(fā)現(xiàn)錯(cuò)誤
  • Continuous delivery(持續(xù)交付):頻繁地將軟件的新版本漓雅,交付給質(zhì)量團(tuán)隊(duì)或者用戶录别,以供評(píng)審
  • Continuous deployment(持續(xù)部署):持續(xù)交付的下一步,指的是代碼通過評(píng)審以后邻吞,自動(dòng)部署到生產(chǎn)環(huán)境
  • 交付后需要進(jìn)行構(gòu)建组题,將源碼轉(zhuǎn)換為可以運(yùn)行的實(shí)際代碼,常用的構(gòu)建工具有 Jenkins抱冷、Strider

AOP

  • 基于 Gradle Transform API 創(chuàng)建 TransForm 崔列,其執(zhí)行時(shí)機(jī)在 class 被打包成 dex 之前
  • 在 TransForm 中通過 javassist 或 asm 修改字節(jié)碼
  • 基于 Gradle Plugin API 自定義插件,應(yīng)用自定義的 TransForm

JetPack

  • LiveData 感知聲明周期原理:像 Glide 一樣給界面添加了無視圖的 Fragment
  • ViewModel 界面旋轉(zhuǎn)短暫銷毀重建時(shí)保存數(shù)據(jù)原理:
    • ViewModel 保存在 ViewModelStore 中
    • 當(dāng) Activity 配置變更銷毀時(shí)旺遮,系統(tǒng)會(huì)調(diào)用 onRetainNonConfigurationInstance 保存 NonConfigurationInstances赵讯,而 ViewModel 就保存在 NonConfigurationInstances 中
    • 重建時(shí) onCreate 方法通過 getLastNonConfigurationInstance 方法獲取到 NonConfigurationInstances,從而獲取到 ViewModelStore
  • JetPack 與 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
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市西傀,隨后出現(xiàn)的幾起案子斤寇,更是在濱河造成了極大的恐慌,老刑警劉巖拥褂,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件娘锁,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡饺鹃,警方通過查閱死者的電腦和手機(jī)莫秆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門间雀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人镊屎,你說我怎么就攤上這事惹挟。” “怎么了缝驳?”我有些...
    開封第一講書人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵连锯,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我用狱,道長(zhǎng)运怖,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任夏伊,我火速辦了婚禮摇展,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘溺忧。我一直安慰自己吗购,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開白布砸狞。 她就那樣靜靜地躺著,像睡著了一般镀梭。 火紅的嫁衣襯著肌膚如雪刀森。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,763評(píng)論 1 307
  • 那天报账,我揣著相機(jī)與錄音研底,去河邊找鬼。 笑死透罢,一個(gè)胖子當(dāng)著我的面吹牛榜晦,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播羽圃,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼乾胶,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了朽寞?” 一聲冷哼從身側(cè)響起识窿,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎脑融,沒想到半個(gè)月后喻频,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡肘迎,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年甥温,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了锻煌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡姻蚓,死狀恐怖宋梧,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情史简,我是刑警寧澤乃秀,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站圆兵,受9級(jí)特大地震影響跺讯,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜殉农,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一刀脏、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧超凳,春花似錦愈污、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至创夜,卻和暖如春杭跪,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背驰吓。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工涧尿, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人檬贰。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓姑廉,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親翁涤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子桥言,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355

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

  • 今天青石的票圈出鏡率最高的,莫過于張藝謀的新片終于定檔了赁严。 一張滿溢著水墨風(fēng)的海報(bào)一次次的出現(xiàn)在票圈里扰柠,也就是老謀...
    青石電影閱讀 10,337評(píng)論 1 2
  • 董多嬌第226天堅(jiān)持分享粉铐,焦點(diǎn)相信,每個(gè)人在每一刻都會(huì)為自己做出一個(gè)決定與選擇卤档,是他們當(dāng)時(shí)認(rèn)為最合適自己的蝙泼,所以任...
    良知良能良知良能閱讀 3,822評(píng)論 1 2
  • 一、jQuery簡(jiǎn)介 JQ是JS的一個(gè)優(yōu)秀的庫(kù)劝枣,大型開發(fā)必備汤踏。在此,我想說的是舔腾,JQ里面很多函數(shù)使用和JS類似溪胶,所...
    Welkin_qing閱讀 12,339評(píng)論 1 6
  • 跑馬燈在項(xiàng)目了其實(shí)應(yīng)用的還比較多,特別是做多媒體的時(shí)候稳诚,音樂視頻藍(lán)牙等等經(jīng)常用到哗脖。 比如音樂的專輯信息,藍(lán)牙通話記...
    江南皮皮閱讀 4,433評(píng)論 1 6
  • 找一個(gè)地方扳还,不被人際關(guān)系網(wǎng)淹沒才避,不被窒息的生活壓力裹挾,忘記錢財(cái)之物氨距,日出而作桑逝,日落而息。繁華的都市不適合俏让,人情往...
    不會(huì)愛的草魚閱讀 1,622評(píng)論 2 0