在字節跳動我是如何當面試官(持續更新)

前言

因爲疫情關係,最近在各大網絡技術交流平臺看到不少同窗的工做狀況心裏仍是蠻觸動的(降薪、變相裁人、辭退等)。可能這並非當下一個廣泛的現象,但仍然使我感覺到Android開發這碗青春飯很差混。於此同時聯繫我內推的同窗不少都處於待業狀態,能感覺到他們心裏的迷茫和焦灼。因而心裏一直有聲音督促我,趕忙寫點面試相關的東西出來吧,哪怕對你們只有一絲絲的幫助。固然此次我會以面試官的角度出發(可能不是一個優秀的面試官),讓你們更加了解字節跳動的面試流程、面試數據和麪試場景等。接下來我會從如下兩個模塊來說解:java

  • 面試注意點
  • 面試題解析

面試注意點

 

01git

代碼能力程序員

是研發面試考察的核心!github

其實說句老實話,研發面試所考察的最核心的能力就是......代碼能力!面試

代碼能力是計算機專業的基礎。可否在有限時間內寫出清晰簡潔、邏輯清晰的代碼,不只能夠考察出候選人是否有紮實的基本功,也可讓面試官對候選人在將來是否可以勝任相應的崗位工做有一個基礎判斷。算法

面試兩場以後我發現,有的候選人剛開始聊項目聊得很是開心,一些細節問題回答得都挺不錯的,可一旦到了手寫代碼這一關,連二分查找都寫不出來的大有人在。json

平時寫的代碼多很少,面試以前有沒有作過準備,有經驗的面試官一眼就能夠判斷出來。因此這裏給你們分享三點建議:設計模式

一、增強基本功,增長代碼量數組

多看優秀的源代碼,認真從效率、邏輯等方面分析他人如何簡潔明晰地實現一個函數,這對提高本身的基本代碼能力有很大的幫助。瀏覽器

二、面試前多作題,保持手感很重要

面試以前多作些練習,這不只能夠加快答題速度,也會讓本身養成較爲規範的答題習慣。

三、覆盤筆試答案,思考更優解

最後,很多面試官喜歡在面試的時候覆盤筆試題目,與候選人討論題目的更優解,從而考察考生是否具有主動思考能力。

02

咱們不反對刷題

不過更但願你們觸類旁通

在面試過程當中,常常會有同窗很是驕傲地坦白道:「我沒有刷題。」

而在這裏我想表明廣大面試官表個態:咱們不反對刷題,甚至但願同窗們在大量作題以後,可以靈活運用、觸類旁通。

大量作題不只能夠在短期內提升同窗們的解題速度,也會在必定程度上幫助你拓展本身的答題思路。

固然,若是發現同窗刷題,面試官也會變種問題,從側面考察同窗是否死記硬背答案。做爲春招的面試官、你將來的潛在同事,咱們更但願同窗們可以靈活貫通。

因此說,該準備準備,該刷題刷題,臨時抱佛腳至少體現了你對面試重視是否是?等你題目刷到必定程度,你就會發現本身的能力有了一個量變到質變的提高。

03

項目描述切忌花哨

突出項目重點,表述邏輯要清晰

參與面試的同窗們大多都有實習經歷。在公司的大環境下,你會在實踐中不斷夯實代碼基礎,也會有更多機會接觸到最新的技術。

咱們但願你們對過往的實習經歷作更深刻的思考,不是簡簡單單描述你在哪裏作了什麼。畢竟面試官須要在短期內看到你的我的能力。發揮主觀能動性,多在幾種不一樣方法之間作比較,給出在思考以後得出的最優解,會顯得你格外不同凡響。

除此以外,思考的邏輯性和表達能力也是面試時考察的重點。在面試時切記要簡化答案,能表達清楚想法就好,項目描述時只須要簡單介紹項目背景,並着重突出項目亮點就能夠啦!千萬不要過分包裝,要知道坦誠清晰但是「字節範兒」中很重要的一點哦~

04

跨專業面試不會受到區別對待

技術實力最重要

面試官們經常會被問到:非計算機專業的同窗跨專業面試會不會受到區別對待?

在這裏我想強調:徹底不會!

不一樣崗位對具體的專業能力要求不一樣,拿算法崗位舉例,只要你代碼基礎功底過硬,數理能力夠強,又對所面試崗位是發自心裏的熱愛,就算你是學挖掘機技術的,面試官們也是想給你發offer的。

算法行業的通用能力就是代碼硬實力。若是不具有這種能力,在實際工做中就總會感受不自信,受人制肘。因此非科班出身的同窗們不用受本身的專業所限,但必定要多多鍛鍊,努力提高本身。

不過這裏也想真心地提醒你們幾句,千萬不要盲從跟風選擇本身的職業方向,每一個領域都有本身廣闊的發展空間,適合本身的纔是最好的。越熱門的崗位對基礎的要求越高,面試官在面試的時候是看獲得筆試成績的,因此還但願你們在面試過程當中誠實一點,不懂裝懂但是會減分的哦!

05

哪些行爲必定是減分項?

除了上述幾點,我還想多囑咐幾句:

雖然面試考察最多的是技術基礎和代碼能力,可是從心理學的角度分析,第一印象也是至關重要的啊喂!

爲了這場面試,逗比的我收斂了表情包,穿上了帥氣的格子衫,還把頭髮梳成了面試官的模樣,你說你穿着拖鞋、臉都不洗就來面試是否是有點傷我心了。

若是同窗們選擇的是視頻面試,但願你們在面試前作好充分的準備工做。面試開始以後,若是遇到候選人遲到、沒有調試設備、網絡不順暢通、麥克風關掉、面試環境嘈雜等狀況,面試官會給必定時間調試,可是面試體驗會受到必定影響,心理上可能會減分的哦!

誠實守信是作人第一要務,也是字節跳動用人的底線。大家要知道,即便是視頻面試,面試官也是能夠看到考生行爲的!答應我,像相似「一邊考試一邊用ipad查答案」這種事情千萬不要幹好嘛!做爲考官的我在攝像頭另外一邊看到了也是很尷尬的......

面試題解析

一、網絡

 

網絡協議模型

應用層:負責處理特定的應用程序細節
HTTP、FTP、DNS

傳輸層:爲兩臺主機提供端到端的基礎通訊
TCP、UDP

網絡層:控制分組傳輸、路由選擇等
IP

鏈路層:操做系統設備驅動程序、網卡相關接口

TCP 和 UDP 區別

TCP 鏈接;可靠;有序;面向字節流;速度慢;較重量;全雙工;適用於文件傳輸、瀏覽器等

  • 全雙工:A 給 B 發消息的同時,B 也能給 A 發
  • 半雙工:A 給 B 發消息的同時,B 不能給 A 發

UDP 無鏈接;不可靠;無序;面向報文;速度快;輕量;適用於即時通信、視頻通話等

TCP 三次握手

A:你能聽到嗎?
B:我能聽到,你能聽到嗎?
A:我能聽到,開始吧

A 和 B 兩方都要能確保:我說的話,你能聽到;你說的話,我能聽到。因此須要三次握手

TCP 四次揮手

A:我說完了
B:我知道了,等一下,我可能還沒說完
B:我也說完了
A:我知道了,結束吧

B 收到 A 結束的消息後 B 可能還沒說完,無法當即回覆結束標示,只能等說完後再告訴 A :我說完了。

POST 和 GET 區別

Get 參數放在 url 中;Post 參數放在 request Body 中
Get 可能不安全,由於參數放在 url 中

HTTPS

HTTP 是超文本傳輸協議,明文傳輸;HTTPS 使用 SSL 協議對 HTTP 傳輸數據進行了加密

HTTP 默認 80 端口;HTTPS 默認 443 端口

優勢:安全
缺點:費時、SSL 證書收費,加密能力仍是有限的,可是比 HTTP 強多了

二、Java 基礎&容器&同步&設計模式

 

StringBuilder、StringBuffer、+、String.concat 連接字符串:

  • StringBuffer 線程安全,StringBuilder 線程不安全
  • +其實是用 StringBuilder 來實現的,因此非循環體能夠直接用 +,循環體不行,由於會頻繁建立 StringBuilder
  • String.concat 實質是 new String ,效率也低,耗時排序:StringBuilder < StringBuffer < concat < +

Java 泛型擦除

  • 修飾成員變量等類結構相關的泛型不會被擦除
  • 容器類泛型會被擦除

ArrayList、LinkedList

ArrayList

基於數組實現,查找快:o(1),增刪慢:o(n)
初始容量爲10,擴容經過 System.arrayCopy 方法

LinkedList

基於雙向鏈表實現,查找慢:o(n),增刪快:o(1)
封裝了隊列和棧的調用

HashMap 、HashTable

HashMap

  • 基於數組和鏈表實現,數組是 HashMap 的主體;鏈表是爲解決哈希衝突而存在的
  • 當發生哈希衝突且鏈表 size 大於閾值時會擴容,JAVA 8 會將鏈表轉爲紅黑樹提升性能
    容許 key/value 爲 null

HashTable

  • 數據結構和 HashMap 同樣
  • 不容許 value 爲 null
  • 線程安全

ArrayMap、SparseArray

ArrayMap

1.基於兩個數組實現,一個存放 hash;一個存放鍵值對。擴容的時候只須要數組拷貝,不須要重建哈希表
2.內存利用率高
3.不適合存大量數據,由於會對 key 進行二分法查找(1000如下)

SparseArray

1.基於兩個數組實現,int 作 key
2.內存利用率高
3.不適合存大量數據,由於會對 key 進行二分法查找(1000如下)

volatile 關鍵字

  • 只能用來修飾變量,適用修飾可能被多線程同時訪問的變量
  • 至關於輕量級的 synchronized,volatitle 能保證有序性(禁用指令重排序)、可見性;後者還能保證原子性
  • 變量位於主內存中,每一個線程還有本身的工做內存,變量在本身線程的工做內存中有份拷貝,線程直接操做的是這個拷貝
  • 被 volatile 修飾的變量改變後會當即同步到主內存,保持變量的可見性。

雙重檢查單例,爲何要加 volatile?

1.volatile想要解決的問題是,在另外一個線程中想要使用instance,發現instance!=null,可是實際上instance還未初始化完畢這個問題

2.將instance =newInstance();拆分爲3句話是。1.分配內存2.初始化3.將instance指向分配的內存空

3.volatile能夠禁止指令重排序,確保先執行2,後執行3

wait 和 sleep

  • sleep 是 Thread 的靜態方法,能夠在任何地方調用
  • wait 是 Object 的成員方法,只能在 synchronized 代碼塊中調用,不然會報 IllegalMonitorStateException 非法監控狀態異常
  • sleep 不會釋放共享資源鎖,wait 會釋放共享資源鎖

lock 和 synchronized

  • synchronized 是 Java 關鍵字,內置特性;Lock 是一個接口
  • synchronized 會自動釋放鎖;lock 須要手動釋放,因此須要寫到 try catch 塊中並在 finally 中釋放鎖
  • synchronized 沒法中斷等待鎖;lock 能夠中斷
  • Lock 能夠提升多個線程進行讀/寫操做的效率
  • 競爭資源激烈時,lock 的性能會明顯的優於 synchronized

可重入鎖

  • 定義:已經獲取到鎖後,再次調用同步代碼塊/嘗試獲取鎖時沒必要從新去申請鎖,能夠直接執行相關代碼
  • ReentrantLock 和 synchronized 都是可重入鎖

公平鎖

  • 定義:等待時間最久的線程會優先得到鎖
  • 非公平鎖沒法保證哪一個線程獲取到鎖,synchronized 就是非公平鎖
  • ReentrantLock 默認時非公平鎖,能夠設置爲公平鎖

樂觀鎖和悲觀鎖

  • 悲觀鎖:線程一旦獲得鎖,其餘線程就掛起等待,適用於寫入操做頻繁的場景;synchronized 就是悲觀鎖
  • 樂觀鎖:假設沒有衝突,不加鎖,更新數據時判斷該數據是否過時,過時的話則不進行數據更新,適用於讀取操做頻繁的場景
  • 樂觀鎖 CAS:Compare And Swap,更新數據時先比較原值是否相等,不相等則表示數據過去,不進行數據更新
  • 樂觀鎖實現:AtomicInteger、AtomicLong、AtomicBoolean

死鎖 4 個必要條件

  • 互斥
  • 佔有且等待
  • 不可搶佔
  • 循環等待

synchronized 原理

  • 每一個對象都有一個監視器鎖:monitor,同步代碼塊會執行 monitorenter 開始,motnitorexit 結束
  • wait/notify 就依賴 monitor 監視器,因此在非同步代碼塊中執行會報 IllegalMonitorStateException 異常

三、Java 虛擬機&內存結構&GC&類加載&四種引用&動態代理

 

JVM

  • 定義:能夠理解成一個虛構的計算機,解釋本身的字節碼指令集映射到本地 CPU 或 OS 的指令集,上層只需關注 Class 文件,與操做系統無關,實現跨平臺
  • Kotlin 就是能解釋成 Class 文件,因此能夠跑在 JVM 上

JVM 內存模型

  • Java 多線程之間是經過共享內存來通訊的,每一個線程都有本身的本地內存
  • 共享變量存放於主內存中,線程會拷貝一份共享變量到本地內存
  • volatile 關鍵字就是給內存模型服務的,用來保證內存可見性和順序性

JVM 內存結構

線程私有:

1.程序計數器:記錄正在執行的字節碼指令地址,若正在執行 Native 方法則爲空
2.虛擬機棧:執行方法時把方法所需數據存爲一個棧幀入棧,執行完後出棧
3.本地方法棧:同虛擬機棧,可是針對的是 Native 方法

線程共享:

1.堆:存儲 Java 實例,GC 主要區域,分代收集 GC 方法會吧堆劃分爲新生代、老年代
2.方法區:存儲類信息,常量池,靜態變量等數據

GC

回收區域:只針對堆、方法區;線程私有區域數據會隨線程結束銷燬,不用回收

回收類型:

1.堆中的對象

  • 分代收集 GC 方法會吧堆劃分爲新生代、老年代
  • 新生代:新建小對象會進入新生代;經過複製算法回收對象
  • 老年代:新建大對象及老對象會進入老年代;經過標記-清除算法回收對象

2.方法區中的類信息、常量池

判斷一個對象是否可被回收:

1.引用計數法
缺點:循環引用

2.可達性分析法
定義:從 GC ROOT 開始搜索,不可達的對象都是能夠被回收的

GC ROOT

1.虛擬機棧/本地方法棧中引用的對象
2.方法區中常量/靜態變量引用的對象

四種引用

  • 強引用:不會被回收
  • 軟引用:內存不足時會被回收
  • 弱引用:gc 時會被回收
  • 虛引用:沒法經過虛引用獲得對象,能夠監聽對象的回收

ClassLoader

類的生命週期:

1.加載;2.驗證;3.準備;4.解析;5.初始化;6.使用;7.卸載

類加載過程:

1.加載:獲取類的二進制字節流;生成方法區的運行時存儲結構;在內存中生成 Class 對象
2.驗證:確保該 Class 字節流符合虛擬機要求
3.準備:初始化靜態變量
4.解析:將常量池的符號引用替換爲直接引用
5.初始化:執行靜態塊代碼、類變量賦值

類加載時機:

1.實例化對象
2.調用類的靜態方法
3.調用類的靜態變量(放入常量池的常量除外)

類加載器:負責加載 class 文件

分類:

1.引導類加載器 - 沒有父類加載器
2.拓展類加載器 - 繼承自引導類加載器
3.系統類加載器 - 繼承自拓展類加載器

雙親委託模型:

當要加載一個 class 時,會先逐層向上讓父加載器先加載,加載失敗纔會本身加載

爲何叫雙親?不考慮自定義加載器,系統類加載器須要網上詢問兩層,因此叫雙親

判斷是不是同一個類時,除了類信息,還必須時同一個類加載器

優勢:

  • 防止重複加載,父加載器加載過了就不必加載了
  • 安全,防止篡改核心庫類

動態代理原理及實現

  • InvocationHandler 接口,動態代理類須要實現這個接口
  • Proxy.newProxyInstance,用於動態建立代理對象
  • Retrofit 應用: Retrofit 經過動態代理,爲咱們定義的請求接口都生成一個動態代理對象,實現請求

四、Android 基礎&性能優化&Framework

 

Activity 啓動模式

  • standard 標準模式
  • singleTop 棧頂複用模式,
    • 推送點擊消息界面
  • singleTask 棧內複用模式,
    • 首頁
  • singleInstance 單例模式,單獨位於一個任務棧中
    • 撥打電話界面
      細節:
    • taskAffinity:任務相關性,用於指定任務棧名稱,默認爲應用包名
    • allowTaskReparenting:容許轉移任務棧

View 工做原理

  • DecorView (FrameLayout)
    • LinearLayout
      • titlebar
      • Content
      • 調用 setContentView 設置的 View

ViewRoot 的 performTraversals 方法調用觸發開始 View 的繪製,而後會依次調用:

  • performMeasure:遍歷 View 的 measure 測量尺寸
  • performLayout:遍歷 View 的 layout 肯定位置
  • performDraw:遍歷 View 的 draw 繪製

事件分發機制

  • 一個 MotionEvent 產生後,按 Activity -> Window -> decorView -> View 順序傳遞,View 傳遞過程就是事件分發,主要依賴三個方法:
  • dispatchTouchEvent:用於分發事件,只要接受到點擊事件就會被調用,返回結果表示是否消耗了當前事件
  • onInterceptTouchEvent:用於判斷是否攔截事件,當 ViewGroup 肯定要攔截事件後,該事件序列都不會再觸發調用此 ViewGroup 的 onIntercept
  • onTouchEvent:用於處理事件,返回結果表示是否處理了當前事件,未處理則傳遞給父容器處理
  • 細節:
    • 一個事件序列只能被一個 View 攔截且消耗
    • View 沒有 onIntercept 方法,直接調用 onTouchEvent 處理
    • OnTouchListener 優先級比 OnTouchEvent 高,onClickListener 優先級最低
    • requestDisallowInterceptTouchEvent 能夠屏蔽父容器 onIntercet 方法的調用

Window 、 WindowManager、WMS、SurfaceFlinger

  • Window:抽象概念不是實際存在的,而是以 View 的形式存在,經過 PhoneWindow 實現
  • WindowManager:外界訪問 Window 的入口,內部與 WMS 交互是個 IPC 過程
  • WMS:管理窗口 Surface 的佈局和次序,做爲系統級服務單獨運行在一個進程
  • SurfaceFlinger:將 WMS 維護的窗口按必定次序混合後顯示到屏幕上

View 動畫、幀動畫及屬性動畫

View 動畫:

  • 做用對象是 View,可用 xml 定義,建議 xml 實現比較易讀
  • 支持四種效果:平移、縮放、旋轉、透明度

幀動畫:

  • 經過 AnimationDrawable 實現,容易 OOM

屬性動畫:

  • 可做用於任何對象,可用 xml 定義,Android 3 引入,建議代碼實現比較靈活
  • 包括 ObjectAnimator、ValuetAnimator、AnimatorSet
  • 時間插值器:根據時間流逝的百分比計算當前屬性改變的百分比
  • 系統預置勻速、加速、減速等插值器
  • 類型估值器:根據當前屬性改變的百分比計算改變後的屬性值
  • 系統預置整型、浮點、色值等類型估值器
  • 使用注意事項:
  • 避免使用幀動畫,容易OOM
  • 界面銷燬時中止動畫,避免內存泄漏
  • 開啓硬件加速,提升動畫流暢性 ,硬件加速:
  • 將 cpu 一部分工做分擔給 gpu ,使用 gpu 完成繪製工做
  • 從工做分攤和繪製機制兩個方面優化了繪製速度

Handler、MessageQueue、Looper

  • Handler:開發直接接觸的類,內部持有 MessageQueue 和 Looper
  • MessageQueue:消息隊列,內部經過單鏈表存儲消息
  • Looper:內部持有 MessageQueue,循環查看是否有新消息,有就處理,沒就阻塞
  • 如何實現阻塞:經過 nativePollOnce 方法,基於 Linux epoll 事件管理機制
  • 爲何主線程不會由於 Looper 阻塞:系統每 16ms 會發送一個刷新 UI 消息喚醒

MVC、MVP、MVVM

  • MVP:Model:處理數據;View:控制視圖;Presenter:分離 Activity 和 Model
  • MVVM:Model:處理獲取保存數據;View:控制視圖;ViewModel:數據容器
    • 使用 Jetpack 組件架構的 LiveData、ViewModel 便捷實現 MVVM

Serializable、Parcelable

  • Serializable :Java 序列化方式,適用於存儲和網絡傳輸,serialVersionUID 用於肯定反序列化和類版本是否一致,不一致時反序列化回失敗
  • Parcelable :Android 序列化方式,適用於組件通訊數據傳遞,性能高,由於不像 Serializable 同樣有大量反射操做,頻繁 GC

Binder

  • Android 進程間通訊的中流砥柱,基於客戶端-服務端通訊方式
  • 使用 mmap 一次數據拷貝實現 IPC,傳統 IPC:用戶A空間->內核->用戶B空間;mmap 將內核與用戶B空間映射,實現直接從用戶A空間->用戶B空間
  • BinderPool 可避免建立多 Service

IPC 方式

  • Intent extras、Bundle:要求傳遞數據能被序列化,實現 Parcelable、Serializable ,適用於四大組件通訊
  • 文件共享:適用於交換簡單的數據實時性不高的場景
  • AIDL:AIDL 接口實質上是系統提供給咱們能夠方便實現 BInder 的工具
    • Android Interface Definition Language,可實現跨進程調用方法
    • 服務端:將暴漏給客戶端的接口聲明在 AIDL 文件中,建立 Service 實現 AIDL 接口並監聽客戶端鏈接請求
    • 客戶端:綁定服務端 Service ,綁定成功後拿到服務端 Binder 對象轉爲 AIDL 接口調用
    • RemoteCallbackList 實現跨進程接口監聽,同個 Binder 對象作 key 存儲客戶端註冊的 listener
    • 監聽 Binder 斷開:1.Binder.linkToDeath 設置死亡代理;2. onServiceDisconnected 回調
  • Messenger:基於 AIDL 實現,服務端串行處理,主要用於傳遞消息,適用於低併發一對多通訊
  • ContentProvider:基於 Binder 實現,適用於一對多進程間數據共享
  • Socket:TCP、UDP,適用於網絡數據交換

Android 系統啓動流程

  • 按電源鍵 -> 加載引導程序 BootLoader 到 RAM -> 執行 BootLoader 程序啓動內核 -> 啓動 init 進程 -> 啓動 Zygote 和各類守護進程 ->
  • 啓動 System Server 服務進程開啓 AMS、WMS 等 -> 啓動 Launcher 應用進程

App 啓動流程

Launcher 中點擊一個應用圖標 -> 經過 AMS 查找應用進程,若不存在就經過 Zygote 進程 fork

進程保活

  • 進程優先級:1.前臺進程 ;2.可見進程;3.服務進程;4.後臺進程;5.空進程
  • 進程被 kill 場景:1.切到後臺內存不足時被殺;2.切到後臺廠商省電機制殺死;3.用戶主動清理
  • 保活方式:
    • 1.Activity 提權:掛一個 1像素 Activity 將進程優先級提升到前臺進程
    • 2.Service 提權:啓動一個前臺服務(API>18會有正在運行通知欄)
    • 3.廣播拉活
    • 4.Service 拉活
    • 5.JobScheduler 定時任務拉活
    • 6.雙進程拉活

網絡優化及檢測

  • 速度:1.GZIP 壓縮(okhttp 自動支持);2.Protocol Buffer 替代 json;3.優化圖片/文件流量;4.IP 直連省去 DNS 解析時間
  • 成功率:1.失敗重試策略;
  • 流量:1.GZIP 壓縮(okhttp 自動支持);2.Protocol Buffer 替代 json;3.優化圖片/文件流量;5.文件下載斷點續傳 ;6.緩存
  • 協議層的優化,好比更優的 http 版本等
  • 監控:Charles 抓包、Network Monitor 監控流量

UI卡頓優化

  • 減小布局層級及控件複雜度,避免過分繪製
  • 使用 include、merge、viewstub
  • 優化繪製過程,避免在 Draw 中頻繁建立對象、作耗時操做

內存泄漏場景及規避

1.靜態變量、單例強引跟生命週期相關的數據或資源,包括 EventBus
2.遊標、IO 流等資源忘記主動釋放
3.界面相關動畫在界面銷燬時及時暫停
4.內部類持有外部類引用致使的內存泄漏

  • handler 內部類內存泄漏規避:1.使用靜態內部類+弱引用 2.界面銷燬時清空消息隊列
  • 檢測:Android Studio Profiler

LeakCanary 原理

  • 經過弱引用和引用隊列監控對象是否被回收
  • 好比 Activity 銷燬時開始監控此對象,檢測到未被回收則主動 gc ,而後繼續監控

OOM 場景及規避

  • 加載大圖:減少圖片
  • 內存泄漏:規避內存泄漏

五、Android 模塊化&熱修復&熱更新&打包&混淆&壓縮

Dalvik 和 ART

  • Dalvik
    • 谷歌設計專用於 Android 平臺的 Java 虛擬機,可直接運行 .dex 文件,適合內存和處理速度有限的系統
    • JVM 指令集是基於棧的;Dalvik 指令集是基於寄存器的,代碼執行效率更優
  • ART
    • Dalvik 每次運行都要將字節碼轉換成機器碼;ART 在應用安裝時就會轉換成機器碼,執行速度更快
    • ART 存儲機器碼佔用空間更大,空間換時間

APK 打包流程

1.aapt 打包資源文件生成 R.java 文件;aidl 生成 java 文件
2.將 java 文件編譯爲 class 文件
3.將工程及第三方的 class 文件轉換成 dex 文件
4.將 dex 文件、so、編譯過的資源、原始資源等打包成 apk 文件
5.簽名
6.資源文件對齊,減小運行時內存

App 安裝過程

  • 首先要解壓 APK,資源、so等放到應用目錄
  • Dalvik 會將 dex 處理成 ODEX ;ART 會將 dex 處理成 OAT;
  • OAT 包含 dex 和安裝時編譯的機器碼

組件化路由實現

ARoute:經過 APT 解析 @Route 等註解,結合 JavaPoet 生成路由表,即路由與 Activity 的映射關係

六、音視頻&FFmpeg&播放器

 

FFmpeg

基於命令方式實現了一個音視頻編輯 App:
https://github.com/yhaolpz/FFmpegCmd

集成編譯了 AAC、MP三、H264 編碼器

播放器原理

視頻播放原理:(mp四、flv)-> 解封裝 -> (mp3/aac、h264/h265)-> 解碼 -> (pcm、yuv)-> 音視頻同步 -> 渲染播放

音視頻同步:

  • 選擇參考時鐘源:音頻時間戳、視頻時間戳和外部時間三者選擇一個做爲參考時鐘源(通常選擇音頻,由於人對音頻更敏感,ijk 默認也是音頻)
  • 經過等待或丟幀將視頻流與參考時鐘源對齊,實現同步

IjkPlayer 原理

集成了 MediaPlayer、ExoPlayer 和 IjkPlayer 三種實現,其中 IjkPlayer 基於 FFmpeg 的 ffplay

音頻輸出方式:AudioTrack、OpenSL ES;視頻輸出方式:NativeWindow、OpenGL ES

如何作好面試突擊,規劃學習方向?

對於程序員來講,要學習的知識內容、技術有太多太多,要想不被環境淘汰就只有不斷提高本身,歷來都是咱們去適應環境,而不是環境來適應咱們!

這裏附上上述的技術體系圖相關的幾十套騰訊、頭條、阿里、美團等公司19年的面試題,把技術點整理成了視頻和PDF(實際上比預期多花了很多精力),包含知識脈絡 + 諸多細節,因爲篇幅有限,這裏以圖片的形式給你們展現一部分。

 

面試題集能夠幫助你查漏補缺,有方向有針對性的學習,爲以後進大廠作準備。可是若是你僅僅是看一遍,而不去學習和深究。那麼這份面試題對你的幫助會頗有限。最終仍是要靠資深技術水平說話。網上學習 Android的資料一大堆,但若是學到的知識不成體系,遇到問題時只是淺嘗輒止,再也不深刻研究,那麼很難作到真正的技術提高。

建議先制定學習計劃,根據學習計劃把知識點關聯起來,造成一個系統化的知識體系。

學習方向很容易規劃,可是若是隻經過碎片化的學習,對本身的提高是很慢的。咱們蒐集整理過這幾年字節跳動,以及騰訊,阿里,華爲,小米等公司的面試題,把面試的要求和技術點梳理成一份大而全的「 Android架構師」面試 Xmind(實際上比預期多花了很多精力),包含知識脈絡 + 分支細節。

 

咱們在搭建這些技術框架的時候,還整理了系統的高級進階教程,會比本身碎片化學習效果強太多;

 

上述【高清技術腦圖】以及【配套的架構技術PDF】能夠 關注我 +簡信【學習】免費獲取

Android學習PDF+架構視頻+面試文檔+源碼筆記

當程序員容易,當一個優秀的程序員是須要不斷學習的,從初級程序員到高級程序員,從初級架構師到資深架構師,或者走向管理,從技術經理到技術總監,每一個階段都須要掌握不一樣的能力。早早肯定本身的職業方向,才能在工做和能力提高中甩開同齡人。

相關文章
相關標籤/搜索