Android面試題集錦(持續更新)

一、java

熟練掌握java是很關鍵的,大公司不僅僅要求你會使用幾個api,更多的是要你熟悉源碼實現原理,甚至要你知道有哪些不足,怎麼改進,還有一些java有關的一些算法,設計模式等等。

(一)java基礎面試知識點

1) java中==和equals和hashCode的區別

== 在用關係操作符 == 比較的是值本身;equals 比較兩個對象的引用是否相等,即 是否指向同一個對象;hashCode 用來鑑定兩個對象是否相等,Object類中的hashCode方法返回對象在內存中地址轉換成的一個int值,所以如果沒有重寫hashCode方法,任何對象的hashCode方法是不相等的。

2) int、char、long各佔多少字節數

4、1或2或4、8

3) int與integer的區別

int 是我們常說的整形數字,是 Java 的 8 個原始數據類型之一。Integer 是 int 對應的包裝類,它有一個 int 類型的字段存儲數據,並且提供了基本操作,比如數學運算、int 和字符串之間轉換等。

4) 談談對java多態的理解

所謂多態就是指程序中定義的引用變量所指向的具體類型和通過該引用變量發出的方法調用在編程時並不確定,而是在程序運行期間才確定,即一個引用變量到底會指向哪個類的實例對象,該引用變量發出的方法調用到底是哪個類中實現的方法,必須在由程序運行期間才能決定。因爲在程序運行時才確定具體的類,這樣,不用修改源程序代碼,就可以讓引用變量綁定到各種不同的類實現上,從而導致該引用變量調用的具體方法隨之改變,即不修改程序代碼就可以改變程序運行時所綁定的具體代碼,讓程序可以選擇多個運行狀態,這就是多態性。實現形式 在Java中有兩種形式可以實現多態。繼承和接口。

5) String、StringBuffer、StringBuilder區別

String 是 Java 語言非常基礎和重要的類,提供了構造和管理字符串的各種基本邏輯。它是典型的 Immutable 類,被聲明成爲 final class,所有屬性也都是 final 的。也由於它的不可變性,類似拼接、裁剪字符串等動作,都會產生新的 String 對象。由於字符串操作的普遍性,所以相關操作的效率往往對應用性能有明顯影響。StringBuffer 是爲解決上面提到拼接產生太多中間對象的問題而提供的一個類,我們可以用 append 或者 add 方法,把字符串添加到已有序列的末尾或者指定位置。StringBuffer 本質是一個線程安全的可修改字符序列,它保證了線程安全,也隨之帶來了額外的性能開銷,所以除非有線程安全的需要,不然還是推薦使用它的後繼者,也就是 StringBuilder。StringBuilder 是 Java 1.5 中新增的,在能力上和 StringBuffer 沒有本質區別,但是它去掉了線程安全的部分,有效減小了開銷,是絕大部分情況下進行字符串拼接的首選。

6) 什是內部類?內部類的作用

定義在類中的類

內部類方法可以訪問該類定義所在作用域中的數據,包括被 private 修飾的私有數據

內部類可以對同一包中的其他類隱藏起來

內部類可以解決 java 單繼承的缺陷

當我們想要定義一個回調函數卻不想寫大量代碼的時候我們可以選擇使用匿名內部類來實現

但是容易內存泄露,因爲持有外部對象。

7) 抽象類和接口區別

接口是對行爲的抽象,他是抽象方法的集合,利用接口可以達到API定義和實現分離的目的。接口,不能實例化;不能包含任何非常量成員,任何field都是隱含着public static final的意義;同時沒有非靜態方法實現,也就是說要麼是抽象方法,要麼是靜態方法。

抽象類是不能實例化的類,有abstract關鍵字修飾class,其目的主要是代碼重用。除了不能實例化,形式上和一般的Java類並沒有太大區別,可以有一個和多個抽象方法,也可以沒有抽象方法。抽象類大多用於抽取相關Java類的共用方法實現或者是共同成員變量,然後通過繼承的方式達到代碼重用的目的。

8) 泛型中extends和super的區別

泛型中extends的主要作用是設定類型通配符的上限,<? extends Fruit>代表的是上界通配符,也就是說這個List中存放的對象都是Fruit以及其子類的對象,這樣我們就不用因爲輸入的List中類型的不同而改變代碼了。

super與extends是完全相反的,其定義的是下界通配符。List<? super Fruit>也就是說List中存放的都是Fruit和它的父類的對象

9) 父類的靜態方法能否被子類重寫

不能,父類的靜態方法能夠被子類繼承,但是不能夠被子類重寫,即使子類中的靜態方法與父類中的靜態方法完全一樣,也是兩個完全不同的方法。

10) 進程和線程的區別

進程是資源分配的最小單位,線程是資源調度的最小單位。

進程有自己的獨立地址空間,每啓動一個進程,系統就會爲它分配地址空間,建立數據表來維護代碼段、堆棧段和數據段,這種操作非常昂貴。

而線程是共享進程中的數據的,使用相同的地址空間,因此CPU切換一個線程的花費遠比進程要小很多,同時創建一個線程的開銷也比進程要小很多。

線程之間的通信更方便,同一進程下的線程共享全局變量、靜態變量等數據,而進程之間的通信需要以通信的方式(IPC)進行。

11) final,finally,finalize的區別

final 可以用來修飾類、方法、變量,分別有不同的意義,final 修飾的 class 代表不可以繼承擴展,final 的變量是不可以修改的,而 final 的方法也是不可以重寫的(override)。finally 則是 Java 保證重點代碼一定要被執行的一種機制。我們可以使用 try-finally 或者 try-catch-finally 來進行類似關閉 JDBC 連接、保證 unlock 鎖等動作。finalize 是基礎類 java.lang.Object 的一個方法,它的設計目的是保證對象在被垃圾收集前完成特定資源的回收。

12) 序列化的方式

實現Serializable接口(隱式序列化)

實現Externalizable接口(顯示序列化)

實現Serializable接口+添加writeObject和readObject方法(顯+隱序列化)

13) Serializable 和Parcelable 的區別

Serializable的作用是爲了保存對象的屬性到本地文件、數據庫、網絡流等以方便數據傳輸,Android的Parcelable的設計初衷是因爲Serializable效率過慢。

內存間數據傳輸時推薦使用Parcelable,如activity間傳輸數據,而Serializable可將數據持久化方便保存,因爲android不同版本Parcelable可能不同,所以不推薦使用Parcelable進行數據持久化。

14) 靜態屬性和靜態方法是否可以被繼承?是否可以被重寫?以及原因?

父類的靜態屬性和方法可以被子類繼承

不可以被子類重寫

因爲靜態方法從程序開始運行後就已經分配了內存,也就是說已經寫死了。所有引用到該方法的對象(父類的對象也好子類的對象也好)所指向的都是同一塊內存中的數據,也就是該靜態方法。子類中如果定義了相同名稱的靜態方法,並不會重寫,而應該是在內存中又分配了一塊給子類的靜態方法,沒有重寫這一說。

15) 靜態內部類的設計意圖

非靜態內部類在編譯完成之後會隱含地保存着一個引用,該引用是指向創建它的外圍類,但是靜態內部類卻沒有。沒有這個引用就意味着:它的創建是不需要依賴於外圍類的。它不能使用任何外圍類的非static成員變量和方法。

16) 成員內部類、靜態內部類、局部內部類和匿名內部類的理解,以及項目中的應用

https://www.cnblogs.com/ldl326308/p/9477566.html

https://blog.csdn.net/nobody_1/article/details/90886330

17) string 轉換成 integer的方式及原理

默認轉成十進制

(二)java深入源碼級的面試題(有難度)

1) 哪些情況下的對象會被垃圾回收機制處理掉?

2) 講一下常見編碼方式?

ASCII編碼:用來表示英文,它使用1個字節表示,其中第一位規定爲0,其他7位存儲數據,一共可以表示128個字符。

拓展ASCII編碼:用於表示更多的歐洲文字,用8個位存儲數據,一共可以表示256個字符

GBK/GB2312/GB18030:表示漢字。GBK/GB2312表示簡體中文,GB18030表示繁體中文。

Unicode編碼:包含世界上所有的字符,是一個字符集。

UTF-8:是Unicode字符的實現方式之一,它使用1-4個字符表示一個符號,根據不同的符號而變化字節長度。

3) utf-8編碼中的中文佔幾個字節;int型幾個字節?

數字佔1個字節,英文字母佔1個字節,少數是漢字每個佔用3個字節,多數佔用4個字節。

4) 靜態代理和動態代理的區別,什麼場景使用?

動態代理是一種方便運行時動態構建代理、動態處理代理方法調用的機制,很多場景都是利用類似機制做到的,比如用來包裝 RPC 調用、面向切面的編程(AOP)。實現動態代理的方式很多,比如 JDK 自身提供的動態代理,就是主要利用了上面提到的反射機制。還有其他的實現方式,比如利用傳說中更高性能的字節碼操作機制,類似 ASM、cglib(基於 ASM)、Javassist 等。通過代理可以讓調用者與實現者之間解耦。

5) Java的異常體系

Exception 和 Error 都是繼承了 Throwable 類,在 Java 中只有 Throwable 類型的實例纔可以被拋出(throw)或者捕獲(catch),它是異常處理機制的基本組成類型。Exception 和 Error 體現了 Java 平臺設計者對不同異常情況的分類。Exception 是程序正常運行中,可以預料的意外情況,可能並且應該被捕獲,進行相應處理。Error 是指在正常情況下,不大可能出現的情況,絕大部分的 Error 都會導致程序(比如 JVM 自身)處於非正常的、不可恢復狀態。既然是非正常情況,所以不便於也不需要捕獲,常見的比如 OutOfMemoryError 之類,都是 Error 的子類。Exception 又分爲可檢查(checked)異常和不檢查(unchecked)異常,可檢查異常在源代碼裏必須顯式地進行捕獲處理,這是編譯期檢查的一部分。前面我介紹的不可查的 Error,是 Throwable 不是 Exception。不檢查異常就是所謂的運行時異常,類似 NullPointerException、ArrayIndexOutOfBoundsException 之類,通常是可以編碼避免的邏輯錯誤,具體根據需要來判斷是否需要捕獲,並不會在編譯期強制要求。

6) 談談你對解析與分派的認識。

7) 修改對象A的equals方法的簽名,那麼使用HashMap存放這個對象實例的時候,會調用哪個equals方法?

8) Java中實現多態的機制是什麼?

9) 如何將一個Java對象序列化到文件裏?

10) 說說你對Java反射的理解

反射機制是 Java 語言提供的一種基礎功能,賦予程序在運行時自省(introspect,官方用語)的能力。通過反射我們可以直接操作類或者對象,比如獲取某個對象的類定義,獲取類聲明的屬性和方法,調用方法或者構造對象,甚至可以運行時修改類定義。

11) 說說你對Java註解的理解

註解,也叫元數據。一種代碼級別的說明,在JDK1.5之後引入的特性,與類、接口、枚舉同一層次。可以聲明在包、類、字段、方法、局部變量、方法參數等前面,來對這些元素進行說明,註釋等。

作用分類:

1)編寫文檔:通過代碼裏的標識的元數據生成文檔【生成文檔doc文檔】

2)代碼分析:通過代碼裏的標識的元數據對代碼進行分析【使用反射】

3)編譯檢查:通過代碼裏的標識的元數據讓編譯器能過實現基本的編譯檢查【Override】

12) 說說你對依賴注入的理解

依賴注入設計原則允許我們移除硬編碼依賴和讓我們的應用低耦合,可擴展和可維護。我們可以通過在Java中實現依賴注入將依賴關係從編譯時移到運行時來解析。

13) 說一下泛型原理,並舉例說明

類型安全, 泛型的主要目標是實現java的類型安全。 泛型可以使編譯器知道一個對象的限定類型是什麼,這樣編譯器就可以在一個高的程度上驗證這個類型

消除了強制類型轉換, 使得代碼可讀性好,減少了很多出錯的機會

Java語言引入泛型的好處是安全簡單。泛型的好處是在編譯的時候檢查類型安全,並且所有的強制轉換都是自動和隱式的,提高代碼的重用率。

泛型的實現是靠類型擦除技術, 類型擦除是在編譯期完成的, 也就是在編譯期, 編譯器會將泛型的類型參數都擦除成它的限定類型,如果沒有則擦除爲object類型之後在獲取的時候再強制類型轉換爲對應的類型。 在運行期間並沒有泛型的任何信息,因此也沒有優化。

14) String爲什麼要設計成不可變的?

字符串常量池(String pool, String intern pool, String保留池) 是Java堆內存中一個特殊的存儲區域, 當創建一個String對象時,假如此字符串值已經存在於常量池中,則不會創建一個新的對象,而是引用已經存在的對象。假若字符串對象允許改變,那麼將會導致各種邏輯錯誤,比如改變一個對象會影響到另一個獨立對象. 嚴格來說,這種常量池的思想,是一種優化手段.

15) Object類的equal和hashCode方法重寫,爲什麼?

(三) 數據結構

1) 常用數據結構簡介

2) 併發集合瞭解哪些?

3) 列舉java的集合以及集合之間的繼承關係

4) 集合類以及集合框架

5) 容器類介紹以及之間的區別(容器類估計很多人沒聽這個詞,Java容器主要可以劃分爲4個部分:List列表、Set集合、Map映射、工具類(Iterator迭代器、Enumeration枚舉類、Arrays和Collections),具體的可以看看這篇博文 Java容器類)

6) List,Set,Map的區別

7) List和Map的實現方式以及存儲方式

8) HashMap的實現原理

9) HashMap數據結構?

10) HashMap源碼理解

11) HashMap如何put數據(從HashMap源碼角度講解)?

12) HashMap怎麼手寫實現?

13) ConcurrentHashMap的實現原理

14) ArrayMap和HashMap的對比

15) HashTable實現原理

16) TreeMap、HashMap和HashTable的區別

Hashtable、HashMap、TreeMap 都是最常見的一些 Map 實現,是以鍵值對的形式存儲和操作數據的容器類型。Hashtable 是早期 Java 類庫提供的一個哈希表實現,本身是同步的,不支持 null 鍵和值,由於同步導致的性能開銷,所以已經很少被推薦使用。HashMap 是應用更加廣泛的哈希表實現,行爲上大致上與 HashTable 一致,主要區別在於 HashMap 不是同步的,支持 null 鍵和值等。通常情況下,HashMap 進行 put 或者 get 操作,可以達到常數時間的性能,所以它是絕大部分利用鍵值對存取場景的首選,比如,實現一個用戶 ID 和用戶信息對應的運行時存儲結構。TreeMap 則是基於紅黑樹的一種提供順序訪問的 Map,和 HashMap 不同,它的 get、put、remove 之類操作都是 O(log(n))的時間複雜度,具體順序可以由指定的 Comparator 來決定,或者根據鍵的自然順序來判斷

17) HashMap與HashSet的區別

18) HashSet與HashMap怎麼判斷集合元素重複?

19) 集合Set實現Hash怎麼防止碰撞

20) Vector、ArrayList和LinkedList的區別,以及應用場景

這三者都是實現集合框架中的 List,也就是所謂的有序集合,因此具體功能也比較近似,比如都提供按照位置進行定位、添加或者刪除的操作,都提供迭代器以遍歷其內容等。但因爲具體的設計區別,在行爲、性能、線程安全等方面,表現又有很大不同。Vector 是 Java 早期提供的線程安全的動態數組,如果不需要線程安全,並不建議選擇,畢竟同步是有額外開銷的。Vector 內部是使用對象數組來保存數據,可以根據需要自動的增加容量,當數組已滿時,會創建新的數組,並拷貝原有數組數據。ArrayList 是應用更加廣泛的動態數組實現,它本身不是線程安全的,所以性能要好很多。與 Vector 近似,ArrayList 也是可以根據需要調整容量,不過兩者的調整邏輯有所區別,Vector 在擴容時會提高 1 倍,而 ArrayList 則是增加 50%。LinkedList 顧名思義是 Java 提供的雙向鏈表,所以它不需要像上面兩種那樣調整容量,它也不是線程安全的。

21) 數組和鏈表的區別

數組是一種線性表數據結構。它用一組連續的內存空間,來存儲一組具有相同類型的數據。最大的特點就是支持隨機訪問,但插入、刪除操作也因此變得比較低效,平均情況時間複雜度爲O(n)。

鏈表它並不需要一塊連續的內存空間,它通過“指針”將一組零散的內存,空間可擴容,比較常用的是單鏈表,雙鏈表和循環鏈表。和數組相比,鏈表更適合插入、刪除操作頻繁的場景,查詢的時間複雜度較高。

22) 二叉樹的深度優先遍歷和廣度優先遍歷的具體實現

23) 堆的結構

24) 堆和樹的區別

25) 堆和棧在內存中的區別是什麼(解答提示:可以從數據結構方面以及實際實現方面兩個方面去回答)?

26) 什麼是深拷貝和淺拷貝

27) 手寫鏈表逆序代碼

28) 講一下對樹,B+樹的理解

29) 講一下對圖的理解

30) 判斷單鏈表成環與否?

31) 鏈表翻轉(即:翻轉一個單項鍊表)

32) 合併多個單有序鏈表(假設都是遞增的)

(四) 線程、多線程和線程池

1) 開啓線程的三種方式?

繼承Thread類、實現Runnable接口、實現Callable接口

2) run()和start()方法區別

start()方法來啓動線程,真正實現了多線程運行,這時無需等待。run()方法當作普通方法的方式調用,程序還是要順序執行,還是要等待run方法體執行完畢。

3) 在Java中wait和seelp方法的不同;

sleep()方法是屬於Thread類中的。而wait()方法,則是屬於Object類中的。

sleep()方法導致了程序暫停執行指定的時間,讓出cpu給其他線程,線程不會釋放對象鎖。而當調用wait()方法的時候,但是他的監控狀態依然保持者,當指定的時間到了又會自動恢復運行狀態。線程會放棄對象鎖,進入等待此對象的等待鎖定池,只有針對此對象調用notify()方法後本線程才進入對象鎖定池準備獲取對象鎖進入運行狀態。

4) 談談wait/notify關鍵字的理解

基類 Object 提供了一些基礎的 wait/notify/notifyAll 方法。如果我們持有某個對象的 Monitor 鎖,調用 wait 會讓當前線程處於等待狀態,直到其他線程 notify 或者 notifyAll。

5) 什麼導致線程阻塞?

線程執行了Thread.sleep

線程執行一段同步代碼,但是尚且無法獲得相關的同步鎖,只能進入阻塞狀態,等到獲取了同步鎖,才能回覆執行。

線程執行了一個對象的wait()方法,直接進入阻塞狀態,等待其他線程執行notify()或者notifyAll()方法。

線程執行某些IO操作,因爲等待相關的資源而進入了阻塞狀態。

6) 線程如何關閉?

使用退出標誌,使線程正常退出,也就是當run方法完成後線程終止

使用stop方法強行終止線程(這個方法不推薦使用,因爲stop和suspend、resume一樣,可能發生不可預料的結果

使用interrupt方法中斷線程。

7) 講一下java中的同步的方法

8) 數據一致性如何保證?

9) 如何保證線程安全?

10) 如何實現線程同步?

11) 兩個進程同時要求寫或者讀,能不能實現?如何防止進程的同步?

12) 線程間操作List

13) Java中對象的生命週期

14) Synchronized用法

15) synchronize的原理

synchronized 代碼塊是由一對兒 monitorenter/monitorexit 指令實現的,Monitor 對象是同步的基本實現單元。

三種不同的鎖:偏斜鎖(Biased Locking)、輕量級鎖和重量級鎖。

所謂鎖的升級、降級,就是 JVM 優化 synchronized 運行的機制,當 JVM 檢測到不同的競爭狀況時,會自動切換到適合的鎖實現,這種切換就是鎖的升級、降級。當沒有競爭出現時,默認會使用偏斜鎖。

16) 談談對Synchronized關鍵字,類鎖,方法鎖,重入鎖的理解

17) static synchronized 方法的多線程訪問和作用

18) 同一個類裏面兩個synchronized方法,兩個線程同時訪問的問題

多個線程訪問同一個類的synchronized方法時, 都是串行執行的 ! 就算有多個cpu也不例外 ! synchronized方法使用了類java的內置鎖, 即鎖住的是方法所屬對象本身. 同一個鎖某個時刻只能被一個執行線程所獲取, 因此其他線程都得等待鎖的釋放. 因此就算你有多餘的cpu可以執行, 但是你沒有鎖, 所以你還是不能進入synchronized方法執行

19) volatile的原理

輕量級的synchronized,只能用來修飾變量

保證了可見性和有序性(不保證原子性),如果一個共享變量被volatile關鍵字修飾,那麼如果一個線程修改了這個共享變量後,其他線程是立馬可知的。

當對volatile變量進行寫操作的時候,JVM會向處理器發送一條lock前綴的指令,將這個緩存中的變量回寫到系統主存中。用到了緩存一致性協議。

20) 談談volatile關鍵字的用法

21) 談談volatile關鍵字的作用

22) synchronized 和volatile 關鍵字的區別

synchronized提供了同步鎖的概念,被synchronized修飾的代碼段可以防止被多個線程同時執行,必須一個線程把synchronized修飾的代碼段都執行完畢了,其他的線程才能開始執行這段代碼。因爲synchronized保證了在同一時刻,只能有一個線程執行同步代碼塊,所以執行同步代碼塊的時候相當於是單線程操作了,那麼線程的可見性、原子性、有序性(線程之間的執行順序)它都能保證了。

區別:

volatile只能作用於變量,使用範圍較小。synchronized可以用在變量、方法、類、同步代碼塊等,使用範圍比較廣。

volatile只能保證可見性和有序性,不能保證原子性。而可見性、有序性、原子性synchronized都可以包證。

volatile不會造成線程阻塞。synchronized可能會造成線程阻塞。

23) synchronized與Lock的區別

lock是一個接口,而synchronized是java的一個關鍵字

synchronized在發生異常時候會自動釋放佔有的鎖,因此不會出現死鎖;而lock發生異常時候,不會主動釋放佔有的鎖

Lock可以通過trylock來知道有沒有獲取鎖,而synchronized不能;

synchronized原始採用的是CPU悲觀鎖機制,即線程獲得的是獨佔鎖。而Lock用的是樂觀鎖方式。所謂樂觀鎖就是,每次不加鎖而是假設沒有衝突而去完成某項操作,如果因爲衝突失敗就重試,直到成功爲止。

24) ReentrantLock 、synchronized和volatile比較

25) ReentrantLock的內部實現

26) lock原理

27) 死鎖的四個必要條件?

互斥條件:一個資源每次只能被一個進程使用,即在一段時間內某 資源僅爲一個進程所佔有。此時若有其他進程請求該資源,則請求進程只能等待。

請求與保持條件:進程已經保持了至少一個資源,但又提出了新的資源請求,而該資源 已被其他進程佔有,此時請求進程被阻塞,但對自己已獲得的資源保持不放。

不可剝奪條件:進程所獲得的資源在未使用完畢之前,不能被其他進程強行奪走,即只能 由獲得該資源的進程自己來釋放(只能是主動釋放)。

循環等待條件: 若干進程間形成首尾相接循環等待資源的關係

28) 怎麼避免死鎖?

29) 對象鎖和類鎖是否會互相影響?

類鎖和對象鎖不是同1個東西,一個是類的Class對象的鎖,一個是類的實例的鎖。也就是說:1個線程訪問靜態synchronized的時候,允許另一個線程訪問對象的實例synchronized方法。反過來也是成立的,因爲他們需要的鎖是不同的。

30) 什麼是線程池,如何使用?

一個線程池包括以下四個基本組成部分:

1、線程池管理器(ThreadPool):用於創建並管理線程池,包括 創建線程池,銷燬線程池,添加新任務;

2、工作線程(PoolWorker):線程池中線程,在沒有任務時處於等待狀態,可以循環的執行任務;

3、任務接口(Task):每個任務必須實現的接口,以供工作線程調度任務的執行,它主要規定了任務的入口,任務執行完後的收尾工作,任務的執行狀態等;

4、任務隊列(taskQueue):用於存放沒有處理的任務。提供一種緩衝機制。

常見線程池有:newSingleThreadExecutor(單線程串行)、newFixedThreadExecutor(固定數量)、newCacheThreadExecutor(可緩存、推薦)、newScheduleThreadExecutor(大小無限制)

31) Java的併發、多線程、線程模型

32) 談談對多線程的理解

線程是由一個主線程和很多個子線程組成的,主線程消失,子線程也會消失,但是子線程消失其中一個主線程不會消失

線程的生命週期分爲5個步驟像人的一生一樣,這5個步驟分別對應了5個方法

新生–>啓動–>運行–>阻塞–>銷燬

33) 多線程有什麼要注意的問題?

線程之間共用進程所有資源,當多線程操作同一個變量的時候,可能會使得結果不正確。

因此要特別注意線程安全的問題。

通常保證線程安全有很多種方式

  • 使用線程鎖
  • 使用串行隊列
  • 使用線程安全的類
  • 使用信號量或runloop使異步看起來像同步在執行
  • 注意任務可能本身就是異步的

34) 談談你對多線程同步機制的理解?

線程同步是爲了確保線程安全,所謂線程安全指的是多個線程對同一資源進行訪問時,有可能產生數據不一致問題,導致線程訪問的資源並不是安全的。如果多線程程序運行結果和單線程運行的結果是一樣的,且相關變量的值與預期值一樣,則是線程安全的。

35) 如何保證多線程讀寫文件的安全?

36) 多線程斷點續傳原理

多線程下載文件時,文件是被分成多個部分,是被不同的線程同時下載的,此時就需要每一條線程都分別需要一個記錄點,和每個線程完成狀態的記錄。只有將所有線程的下載狀態都處於完成狀態時,才能表示文件下載完成。

1、首先獲取要下載文件的長度,用來設置RomdomAccessFile(本地文件)的長度

2、實時保存文件的下載進度(此功能可以用數據庫來實現)

3、中斷後再次下載,讀取進度,再從上次的下載進度繼續下載,並在本地的文件續續寫如。

獲取文件長度:fileLength = HttpUrlConnection.getContentLength()

每條線程需要下載的大小 = fileLength / Thread_Num

37) 斷點續傳的實現

二、Android

Android面試題包括Android基礎,還有一些源碼級別的、原理這些等。所以想去大公司面試,一定要多看看源碼和實現方式,常用框架可以試試自己能不能手寫實現一下,鍛鍊一下自己。

(一)Android基礎知識點

1) 四大組件是什麼

Activity/Service/BroadCast Recevicer/Content provider

2) 四大組件的生命週期和簡單用法

627C8B04-E054-48D2-8452-3AC69CE094F44BC63369-47E8-4D61-872C-715A6DCF133A

3) Activity之間的通信方式

在Intent跳轉時攜帶數據

藉助類的靜態變量

藉助全局變量 Application

藉助Service服務

藉助外部存儲來實現通訊

藉助 SharedPreference

使用Android數據庫 SQLite

使用 File本地文件

4) 橫豎屏切換的時候,Activity 各種情況下的生命週期

Activity未配置configChanges屬性,切到橫屏後,再切回豎屏時,會走兩遍onPause——onSaveInstanceState——onStop——onDestroy——onCreate——onStart——onRestoreInstanceState——onResume 生命週期方法

只要隨意配置了configChanges屬性,切到橫屏和再切到豎屏,生命週期調用順序都表現爲onConfigurationChanged

5) Activity與Fragment之間生命週期比較

6) Activity上有Dialog的時候按Home鍵時的生命週期

onPause() -> onStop()

對話框的出現並沒有使Activity進入後臺。而是點擊Home鍵才使Activity進入後臺工作

7) 兩個Activity 之間跳轉時必然會執行的是哪幾個方法?

當在A 裏面激活B 組件的時候, A會調用onPause()方法,然後B調用onCreate() ,onStart(), onResume()。

這個時候B覆蓋了A的窗體, A會調用onStop()方法。

如果B是個透明的窗口,或者是對話框的樣式, 就不會調用A的onStop()方法。

如果B已經存在於Activity棧中,B就不會調用onCreate()方法。

8) Activity的四種啓動模式對比

標準模式(standard)每次啓動一個標準模式的Activity都會重新創建一個新的實例,不管這個Activity之前是否已經存在實例

棧頂複用模式(singleTop)新啓動的Activity已經位於任務戰的棧頂,那麼此Activity不會被重新創建,只會重新調用 onNewIntent 方法,這個Activity的onCreate、onStart都不會被系統調用。如果新Activity實例已經存在但不在棧頂,那麼重新創建 Activity 並放入棧頂

棧內複用模式(singleTask)一個棧中同一個Activity只存在唯一一個實例,無論是否在棧頂,只要存在實例,都不會重新創建,和 singleTop 一樣會重新調用 onNewIntent 方法。需要注意的是:如果一個Activity被設置爲singleTask模式,那麼當棧內已經存在該Activity實例時,再啓動該Activity,會讓該Activity實例之上的Activity被出棧

單例模式(singleInstance)這是一種加強的singleTask模式,它除了具有singleTask模式的所有特性外,還加強了一點,那就是此種模式的Activity只能單獨地位於一個任務棧中,不同的應用去打開這個activity 共享公用的同一個activity。他會運行在自己單獨,獨立的任務棧裏面,並且任務棧裏面只有他一個實例存在。應用場景:呼叫來電界面。

9) Activity狀態保存與恢復

臨時性數據

onSaveInstanceState調用的原則是系統有未經你的許可銷燬Activity的可能。那麼onSaveInstanceState有下面幾種情況會調用:

按下HOME鍵、長按HOME鍵切換到了其他APP、橫豎屏切換、Activity的導航、鎖定屏幕

onRestoreInstanceState被調用的原則是Activity被銷燬了,而不是可能被銷燬了。

持久性數據

在onResume和onPause方法中做,可以把數據保存在數據庫或者SharedPreference中。然而在生命週期函數中不適合做耗時的操作

**10) 如何實現Fragment的滑動?**ViewPager+Fragment

11) fragment之間傳遞數據的方式?

定義數據接口,在Activity中實現該接口,並實現接口中定義的方法,在Fragment A中聲明接口對象,並調用接口中的方法,Activity中的接口回調中,向Fragment B傳遞數據

EventBus傳值

12) Activity 怎麼和Service 綁定?

Activity 通過 bindService(Intent service, ServiceConnection conn, int flags) 跟服務 進行綁定, 當綁定成功的時候服務會將代理對象通過 onBind() 方法傳給 conn, 這樣我們就拿到了服務提供的服務代理對象

13) 怎麼在Activity 中啓動自己對應的Service?

14) service和activity怎麼進行數據交互?

Activity和Service的交互方式主要有以下幾種:通過廣播進行交互、通過共享文件、Messenger、AIDL

15) Service的開啓方式

16) 請描述一下Service 的生命週期

  • onCreate():

首次創建服務時,系統將調用此方法。如果服務已在運行,則不會調用此方法,該方法只調用一次。

  • onStartCommand():

    當另一個組件通過調用startService()請求啓動服務時,系統將調用此方法。

  • onDestroy():

    當服務不再使用且將被銷燬時,系統將調用此方法。

  • onBind():

    當另一個組件通過調用bindService()與服務綁定時,系統將調用此方法。

  • onUnbind():

    當另一個組件通過調用unbindService()與服務解綁時,系統將調用此方法。

  • onRebind():

    當舊的組件與服務解綁後,另一個新的組件與服務綁定,onUnbind()返回true時,系統將調用此方法。

17) 請描述一下廣播BroadcastReceiver的理解

18) 廣播的分類

19) 廣播使用的方式和場景

20) BroadcastReceiver,LocalBroadcastReceiver 區別

BroadcastReceiver用於應用之間的傳遞消息;而LocalBroadcastManager用於應用內部傳遞消息,比broadcastReceiver更加高效。

BroadcastReceiver使用的Content API,所以本質上它是跨應用的,所以在使用它時必須要考慮到不要被別的應用濫用;LocalBroadcastManager不需要考慮安全問題,因爲它只在應用內部有效。

21) AlertDialog,popupWindow,Activity區別

AlertDialog 是非阻塞式對話框;而PopupWindow 是阻塞式對話框。

兩者最根本的區別在於有沒有新建一個 window,PopupWindow 沒有新建,而是通過 WMS 將 View 加到 DecorView;Dialog 是新建了一個 window (PhoneWindow),相當於走了一遍 Activity 中創建 window 的流程。

22) Application 和 Activity 的 Context 對象的區別

Acitiivity 繼承自ContextThemeWrapper—>再繼承ContextWrapper—>Context。

Appliction 、Service繼承自ContextWrapper—>再繼承Context。

Application、Service 和 Activity 最終都是繼承自Context,所以它們是同一個上下文。

23) Android屬性動畫特性

屬性動畫可以對任何對象的屬性做動畫而不僅僅是View,甚至可以沒有對象。除了作用對象進行擴展外,屬性動畫的效果也加強了,不僅能實現View動畫的4中效果,還能實現其它多種效果,這些效果都是通過ValuAnimator或ObjectAnimator、AnimatorSet等來實現的。

24) 如何導入外部數據庫?

25) LinearLayout、RelativeLayout、FrameLayout的特性及對比,並介紹使用場景。

26) 談談對接口與回調的理解

27) 回調的原理

回調是一段可執行的代碼通過參數傳遞給別一段代碼,以期望在一個合適的時間調用這個參數

28) 寫一個回調demo

Callback.java
public interface Callback {
    void printFinished(String msg);
}
Printer.java
public class Printer {
    public void print(Callback callback) {
        System.out.println("正在打印 . . . ");
        try {
            Thread.currentThread();
            Thread.sleep(3000);// 毫秒
        } catch (Exception e) {
            e.printStackTrace();
        }
        callback.printFinished("打印完成");
    }
}
People.java
public class People {
    Printer printer = new Printer();
    // 同步回調
    public void goToPrintSyn(Callback callback) {
        printer.print(callback);
    }
    // 異步回調
    public void goToPrintASyn(Callback callback) {
        new Thread(new Runnable() {
            public void run() {
                printer.print(callback);
            }
        }).start();
    }
}

29) 介紹下SurfView

30) RecycleView的使用

31) 序列化的作用,以及Android兩種序列化的區別

32) 差值器

Interpolator設置 屬性值 從初始值過渡到結束值 的變化規律的一個接口,如勻速、加速 & 減速 等等,即確定了 動畫效果變化的模式,如勻速變化、加速變化 等等

應用場景:實現非線性運動的動畫效果

33) 估值器

TypeEvaluator設置 屬性值 從初始值過渡到結束值 的變化具體數值的接口

插值器(Interpolator)決定 值 的變化規律(勻速、加速blabla),即決定的是變化趨勢;而接下來的具體變化數值則交給估值器

屬性動畫特有的屬性,協助插值器 實現非線性運動的動畫效果

34) Android中數據存儲方式

五種數據存儲 :SharePreferences、SQLite、Contert Provider、File、網絡存儲

(二)Android源碼相關分析

1) Android動畫框架實現原理

Android 動畫就是通過 ParentView 來不斷調整 ChildView 的畫布座標系來實現的

這其中又涉及到兩個重要的類型,Animation 和 Transformation,這兩個類是實現動畫的主要的類,Animation 中主要定義了動畫的一些屬性比如開始時間、持續時間、是否重複播放等,這個類主要有兩個重要的函數:getTransformation 和 applyTransformation,在 getTransformation 中 Animation 會根據動畫的屬性來產生一系列的差值點,然後將這些差值點傳給 applyTransformation,這個函數將根據這些點來生成不同的 Transformation,Transformation 中包含一個矩陣和 alpha 值

2) Android各個版本API的區別

//V9.0:劉海屏的適配、電源管理、開發的應用默認不支持Http
//V8.0:通知欄適配(Notifcation)、廣播限制、後臺服務限制 8.0以上創建的前臺Service需要發送一個Notification,否則Service會Anr
//V7.0:多窗口支持、文件讀寫權限適配、引入一項新的應用簽名方案 :APK Signature Scheme v2、需要適配FileProvider,否則應用會崩潰。app之間的私有文件共享只能用FileProvider這種方式.
//V6.0:Android 動態權限申請、指紋識別、移除HttpClient庫
//V5.0:虛擬機由Dalvik替換爲Art虛擬機,Dalvik 使用JIT編譯器,Art是AOT編譯器、Materil Design設計規範、WebView cookie 存儲問題
//V4.0:沉浸式狀態欄、WebView webview調試功能、WebView 增加對 https請求限制需要去驗證https證書

3) Requestlayout,onlayout,onDraw,DrawChild區別與聯繫

requestLayout()方法對View樹進行重新佈局,過程包括了measure()和layout()過程,但不會調用draw()過程,即不會發生重新繪製視圖過程。

onLayout()的調用時機是:View需要給自己設置大小和位置了或者ViewGroup需要給子View和ViewGroup自身時調用。

View的繪製流程一共包括三步:①測量measure;②佈局layout;③繪製draw;onDraw()方法就是在第三布繪製時發生,開發者已經測量好View的大小,設置好View的佈局,剩下最後一步就是,具體畫出這個佈局。畫的方法就是onDraw(),每個View都需要利用這個方法畫出自己,ViewGroup除非設置了背景,否則不用調用該方法。

drawChild()去重新回調每個子視圖的draw()方法

4) invalidate和postInvalidate的區別及使用

當Invalidate()被調用的時候,View的OnDraw()就會被調用;Invalidate()是刷新UI,UI更新必須在主線程,所以invalidate必須在UI線程中被調用,如果在子線程中更新視圖的就調用postInvalidate()。

postInvalidate()實際調用的方法,mHandler.sendMessageDelayed,在子線程中用handler發送消息,所以才能在子線程中使用。

5) Activity-Window-View三者的差別

Activity 是四大組件之一,也是我們的界面載體,可以展示頁面;而 View 實際上就是一個一個的視圖,這些視圖可以搭載在一個 Layout 文件上,通過 Activity 的 setContentView() 方法傳遞給 Activity;Window 是一個窗體,每個 Activity 對應一個 Window,通常我們在代碼中用 getWindow() 來獲取它。

每個 Activity 包含了一個 Window 對象,這個對象是由 PhoneWindow 做的實現。而 PhoneWindow 將 DecorView 作爲了一個應用窗口的根 View,這個 DecorView 又把屏幕劃分爲了兩個區域:一個是 TitleView,一個是 ContentView,而我們平時在 Xml 文件中寫的佈局正好是展示在 ContentView 中的。

A9AE4EB0-976E-45FF-8F19-D8559ADA436B

6) 談談對Volley的理解

7) 如何優化自定義View

8) 低版本SDK如何實現高版本api?

9) 描述一次網絡請求的流程

10) HttpUrlConnection 和 okhttp關係

11) Bitmap對象的理解

12) looper架構

13) ActivityThread,AMS,WMS的工作原理

14) 自定義View如何考慮機型適配

15) 自定義View的事件

16) AstncTask+HttpClient 與 AsyncHttpClient有什麼區別?

17) LaunchMode應用場景

18) AsyncTask 如何使用?

19) SpareArray原理

20) 請介紹下ContentProvider 是如何實現數據共享的?

21) AndroidService與Activity之間通信的幾種方式

22) IntentService原理及作用是什麼?

23) 說說Activity、Intent、Service 是什麼關係

24) ApplicationContext和ActivityContext的區別

25) SP是進程同步的嗎?有什麼方法做到同步?

26) 談談多線程在Android中的使用

27) 進程和 Application 的生命週期

28) 封裝View的時候怎麼知道view的大小

29) RecycleView原理

30) AndroidManifest的作用與理解

(三)常見的一些原理性問題

1) Handler機制和底層實現

2) Handler、Thread和HandlerThread的差別

3) handler發消息給子線程,looper怎麼啓動?

4) 關於Handler,在任何地方new Handler 都是什麼線程下?

5) ThreadLocal原理,實現及如何保證Local屬性?

6) 請解釋下在單線程模型中Message、Handler、Message Queue、Looper之間的關係

7) 請描述一下View事件傳遞分發機制

8) Touch事件傳遞流程

9) 事件分發中的onTouch 和onTouchEvent 有什麼區別,又該如何使用?

10) View和ViewGroup分別有哪些事件分發相關的回調方法

11) View刷新機制

在Android的View刷新機制中,父View負責刷新(invalidateChild)、佈局(layoutChild)顯示子View。而當子View需要刷新時,則是通知父View刷新子view來完成。

12) View繪製流程

View的繪製基本分爲measure、layout、draw 過程

測量一個比較重要的概念是,MeasureSpec一共有三種模式

UPSPECIFIED : 父容器對於子容器沒有任何限制,子容器想要多大就多大

EXACTLY: 父容器已經爲子容器設置了尺寸,子容器應當服從這些邊界,不論子容器想要多大的空間。

AT_MOST:子容器可以是聲明大小內的任意大小

https://www.jianshu.com/p/5a71014e7b1b

13) 自定義控件原理

14) 自定義View如何提供獲取View屬性的接口?

15) Android代碼中實現WAP方式聯網

16) AsyncTask機制

17) AsyncTask原理及不足

18) 如何取消AsyncTask?

19) 爲什麼不能在子線程更新UI?

20) ANR產生的原因是什麼?

在Android裏,應用程序的響應性是由Activity Manager和WindowManager系統服務監視的 。當它監測到以下情況中的一個時,Android就會針對特定的應用程序顯示ANR:

1.在5秒內沒有響應輸入的事件(例如,按鍵按下,屏幕觸摸)

2.BroadcastReceiver在10秒內沒有執行完畢

3.service是20

造成以上兩點的原因有很多,比如在主線程中做了非常耗時的操作,比如說是下載,io異常等。

21) ANR定位和修正

22) oom是什麼?

23) 什麼情況導致oom?

24) 有什麼解決方法可以避免OOM?

25) Oom 是否可以try catch?爲什麼?

26) 內存泄漏是什麼?

27) 什麼情況導致內存泄漏?

28) 如何防止線程的內存泄漏?

29) 內存泄露場景的解決方法

30) 內存泄漏和內存溢出區別?

**31) LruCache默認緩存大小。**基本上設置爲手機內存的1/8

32) ContentProvider的權限管理(解答:讀寫分離,權限控制-精確到表級,URL控制)

33) 如何通過廣播攔截和abort一條短信?

在清單文件中註冊廣播接收器,設置該廣播接收器優先級,儘量設高一點

創建一個BroadcastReceiver來實現廣播的處理,並設置攔截器abortBroadcast();

**34) 廣播是否可以請求網絡?**子線程可以

**35) 廣播引起anr的時間限制是多少?**10s

36) 計算一個view的嵌套層級

while(view.getParent() != null) {
  count++;
  View = view.getParents();
}

37) Activity棧

38) Android線程有沒有上限?

39) 線程池有沒有上限?

40) ListView重用的是什麼?

41) Android爲什麼引入Parcelable?

Serializable 會使用反射,序列化和反序列化過程需要大量 I/O 操作, Parcelable 自已實現封送和解封(marshalled &unmarshalled)操作不需要用反射,數據也存放在 Native 內存中,效率要快很多。

42) 有沒有嘗試簡化Parcelable的使用?

(四)開發中常見的一些問題

1) ListView 中圖片錯位的問題是如何產生的?

2) 混合開發有了解嗎?

3) 知道哪些混合開發的方式?說出它們的優缺點和各自使用場景?(解答:比如:RN,weex,H5,小程序,WPA等。做Android的瞭解一些前- 端js等還是很有好處的);

4) 屏幕適配的處理技巧都有哪些?

5) 服務器只提供數據接收接口,在多線程或多進程條件下,如何保證數據的有序到達?

6) 動態佈局的理解

7) 怎麼去除重複代碼?

8) 畫出 Android 的大體架構圖

3CA9E985-294E-47F4-8308-594E9699A10E

應用層:用Java語言編寫的運行在虛擬機上的程序,如電子郵件、短信、日曆、瀏覽器和聯繫人等

應用框架層:系統組件API(Content Provicers、Views、Manager(Activity、Notification、Resource、Telephony、Window))

系統運行庫(原生C/C++庫及Android運行庫):當使用Android應用框架時,Android系統會通過一些C/C++庫來支持我們使用的各個組件,使其更好的爲我們服務,比如SQLite、Webkit。

Linux內核:Android核心系統服務,如安全性、內存管理、進程管理、網絡協議棧和驅動模型都依賴於該內核。Linux內核也是作爲硬件與軟件棧的抽象層。

9) Recycleview和ListView的區別

RecyclerView比ListView多兩級緩存,支持多個離ItemView緩存,支持開發者自定義緩存處理邏輯,支持所有RecyclerView共用同一個RecyclerViewPool(緩存池)。

RecyclerView更大的亮點在於提供了局部刷新的接口,通過局部刷新,就能避免調用許多無用的bindView。ListView和RecyclerView最大的區別在於數據源改變時的緩存的處理邏輯,ListView是"一鍋端",將所有的mActiveViews都移入了二級緩存mScrapViews,而RecyclerView則是更加靈活地對每個View修改標誌位,區分是否重新bindView.

https://www.jianshu.com/p/257c279a3493

10) ListView圖片加載錯亂的原理和解決方案

1>:某一個位置的元素剛進入屏幕開始請求圖片,圖片沒有下載完成,就被移出屏幕,根據ListView工作原理可知,被移出屏幕的控件會很快的被重複利用起來,如果在這個時候之前發起圖片的請求有了響應,會將剛纔位置的圖片顯示到當前位置,雖然他們位置不同,卻共用着同一個ImageView實例,這個時候會出現圖片亂序;

2>:新進入屏幕的元素也會去請求圖片,等圖片下載完的時候會設置到同樣的ImageView,因此就出現先顯示一張圖片,然後又變爲另一張圖片,就造成圖片變來變去;

解決方案:

1>:在getView()方法中用url地址給ImageView設置tag標記;

2>:在onPostExecute()方法中調用 mListView.findViewWithTag(imageUrl) 獲取ImageView實例,然後判斷如果不爲null,就把drawable圖片設置到該ImageView控件上即可;

11) 動態權限適配方案,權限組的概念

**12) Android系統爲什麼會設計ContentProvider?談談你對ContentProvider的理解

ContentProvider應用程序間非常通用的共享數據的一種方式,也是Android官方推薦的方式。Android中許多系統應用都使用該方式實現數據共享,比如通訊錄、短信等。

設計用意在於:

封裝。對數據進行封裝,提供統一的接口,使用者完全不必關心這些數據是在DB,XML、Preferences或者網絡請求來的。當項目需求要改變數據來源時,使用我們的地方完全不需要修改。

提供一種跨進程數據共享的方式。

就是數據更新通知機制了。因爲數據是在多個應用程序中共享的,當其中一個應用程序改變了這些共享數據的時候,它有責任通知其它應用程序,讓它們知道共享數據被修改了,這樣它們就可以作相應的處理。

ContentResolver接口的notifyChange函數來通知那些註冊了監控特定URI的ContentObserver對象,使得它們可以相應地執行一些處理。ContentObserver可以通過registerContentObserver進行註冊。

ContentProvider和調用者在同一個進程,ContentProvider的方法(query/insert/update/delete等)和調用者在同一線程中;

ContentProvider和調用者在不同的進程,ContentProvider的方法會運行在它自身所在進程的一個Binder線程中。

13) 說說ContentProvider、ContentResolver、ContentObserver 之間的關係

ContentProvider——內容提供者, 在android中的作用是對外共享數據,也就是說你可以通過ContentProvider把應用中的數據共享給其他應用訪問,其他應用可以通過ContentProvider 對你應用中的數據進行添刪改查。

ContentResolver——內容解析者, 其作用是按照一定規則訪問內容提供者的數據(其實就是調用內容提供者自定義的接口來操作它的數據)。

ContentObserver——內容觀察者,目的是觀察(捕捉)特定Uri引起的數據庫的變化,繼而做一些相應的處理,它類似於數據庫技術中的觸發器(Trigger),當ContentObserver所觀察的Uri發生變化時,便會觸發它。

14) 下拉狀態欄是不是影響activity的生命週期

不會

15) 如果在onStop的時候做了網絡請求,onResume的時候怎麼恢復?

16) Bitmap 使用時候注意什麼?

要選擇合適的圖片規格(ALPHA_8、ARGB_4444、ARGB_8888、RGB_565)分別佔用1、2、4、2byte

減低採樣率。BitmapFactory.Options inSampleSize inJustDecodeBounds

複用內存。通過軟引用複用內存塊

及時回收。即,recycle

壓縮圖片。compress

儘量不要使用setImageBitmap或setImageResource或BitmapFactory.decodeResource來設置一張大圖,因爲這些函數在完成decode後,最終都是通過java層的createBitmap來完成的,需要消耗更多內存,可以通過BitmapFactory.decodeStream方法

17) Bitmap的recycler()

18) Android中開啓攝像頭的主要步驟

19) ViewPager使用細節,如何設置成每次只初始化當前的Fragment,其他的不初始化?

20) 點擊事件被攔截,但是想傳到下面的View,如何操作?

21) 微信主頁面的實現方式

22) 微信上消息小紅點的原理

三、高級開發技術面試題

這裏講的是大公司需要用到的一些高端Android技術,這裏專門整理了一個文檔,希望大家都可以看看。這些題目有點技術含量,需要好點時間去研究一下的。

(一)圖片

1) 圖片庫對比

2) 圖片庫的源碼分析

3) 圖片框架緩存實現

4) LRUCache原理

5) 圖片加載原理

6) 自己去實現圖片庫,怎麼做?

7) Glide源碼解析

8) Glide使用什麼緩存?

9) Glide內存緩存如何控制大小?

(二)網絡和安全機制

1) 網絡框架對比和源碼分析

2) 自己去設計網絡請求框架,怎麼做?

3) okhttp源碼

BD71EC21-C489-4350-85BC-B51FCCCFFF11

4) 網絡請求緩存處理,okhttp如何處理網絡緩存的

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-7JZERVo8-1583051079011)(/var/folders/6w/lw3r34g115sdl_h8jg_jff4c0000gn/T/com.yinxiang.Mac/com.yinxiang.Mac/WebKitDnD.ZVB9bq/112EEDBE-082D-410B-B731-F0BE0B86F7AC.png)]

5) 從網絡加載一個10M的圖片,說下注意事項

6) TCP的3次握手和四次揮手

請求 -> 應答 -> 應答之應答

例:A:您好,我是 A。B:您好 A,我是 B。A:您好 B。

揮手:A:B 啊,我不想玩了。B:哦,你不想玩了啊,我知道了。B:A 啊,好吧,我也不玩了,拜拜。A:好的,拜拜。

7) TCP與UDP的區別

TCP 是面向連接的,UDP 是面向無連接的。TCP 會三次握手,而 UDP 不會。

TCP 提供可靠交付。通過 TCP 連接傳輸的數據,無差錯、不丟失、不重複、並且按序到達。UDP 繼承了 IP 包的特性,不保證不丟失,不保證按順序到達。

TCP 是面向字節流的。發送的時候發的是一個流,沒頭沒尾。而 UDP 繼承了 IP 的特性,基於數據報的,一個一個地發,一個一個地收。

TCP 是可以有擁塞控制的。它意識到包丟棄了或者網絡的環境不好了,就會根據情況調整自己的行爲,看看是不是發快了,要不要發慢點。UDP 就不會,應用讓我發,我就發,管它洪水滔天。

因而 TCP 其實是一個有狀態服務,通俗地講就是有腦子的,裏面精確地記着發送了沒有,接收到沒有,發送到哪個了,應該接收哪個了,錯一點兒都不行。而 UDP 則是無狀態服務。通俗地說是沒腦子的,天真無邪的,發出去就發出去了。

8) TCP與UDP的應用

UDP使用場景:需要資源少,在網絡情況比較好的內網,或者對於丟包不敏感的應用。不需要一對一溝通,建立連接,而是可以廣播的應用。需要處理速度快,時延低,可以容忍少數丟包,但是要求即便網絡擁塞,也毫不退縮,一往無前的時候。

9) HTTP協議

10) HTTP1.0與2.0的區別

HTTP1.x的解析是基於文本。HTTP2.0的協議解析決定採用二進制格式,實現方便且健壯。

HTTP2.0多路複用,即鏈接共享

HTTP1.x的header帶有大量信息,而且每次都要重複發送,

HTTP2.0使用encoder來減少需要傳輸的header大小,通訊雙方各自cache一份header fields表,既避免了重複header的傳輸,又減小了需要傳輸的大小。

HTTP2.0也具有server push功能。

11) HTTP報文結構

1F7FA46D-856F-4A08-BC9C-C062BB2CFC10

HTTP 的報文大概分爲三大部分。第一部分是請求行,第二部分是請求的首部,第三部分纔是請求的正文實體。

12) HTTP與HTTPS的區別以及如何實現安全性

13) 如何驗證證書的合法性?

14) https中哪裏用了對稱加密,哪裏用了非對稱加密,對加密算法(如RSA)等是否有了解?

CABE9C35-ACC4-4F10-B7BB-6AAD2E37A55D

15) client如何確定自己發送的消息被server收到?

16) 談談你對WebSocket的理解

17) WebSocket與socket的區別

18) 談談你對安卓簽名的理解。

19) 請解釋安卓爲啥要加簽名機制?

20) 視頻加密傳輸

21) App 是如何沙箱化,爲什麼要這麼做?

22) 權限管理系統(底層的權限是如何進行 grant 的)?

(三)數據庫

1) sqlite升級,增加字段的語句

2) 數據庫框架對比和源碼分析

3) 數據庫的優化

4) 數據庫數據遷移問題

(四)插件化、模塊化、組件化、熱修復、增量更新、Gradle

1) 對熱修復和插件化的理解

2) 插件化原理分析

3) 模塊化實現(好處,原因)

4) 熱修復,插件化

5) 項目組件化的理解

6) 描述清點擊 Android Studio 的 build 按鈕後發生了什麼

(五)架構設計和設計模式

  1. 談談你對Android設計模式的理解**

2) MVC MVP MVVM原理和區別

3) 你所知道的設計模式有哪些?

4) 項目中常用的設計模式

5) 手寫生產者/消費者模式

6) 寫出觀察者模式的代碼

7) 適配器模式,裝飾者模式,外觀模式的異同?

8) 用到的一些開源框架,介紹一個看過源碼的,內部實現過程。

9) 談談對RxJava的理解

10) RxJava的功能與原理實現

11) RxJava的作用,與平時使用的異步操作來比的優缺點

12) 說說EventBus作用,實現方式,代替EventBus的方式

13) 從0設計一款App整體架構,如何去做?

14) 說一款你認爲當前比較火的應用並設計(比如:直播APP,P2P金融,小視頻等)

15) 談談對java狀態機理解

16) Fragment如果在Adapter中使用應該如何解耦?

17) Binder機制及底層實現

18) 對於應用更新這塊是如何做的?(解答:灰度,強制更新,分區域更新)?

19) 實現一個Json解析器(可以通過正則提高速度)

20) 統計啓動時長,標準

(六)性能優化

1) 如何對Android 應用進行性能分析以及優化?

2) ddms 和 traceView

3) 性能優化如何分析systrace?

4) 用IDE如何分析內存泄漏?

5) Java多線程引發的性能問題,怎麼解決?

6) 啓動頁白屏及黑屏解決?

7) 啓動太慢怎麼解決?

8) 怎麼保證應用啓動不卡頓?

9) App啓動崩潰異常捕捉

10) 自定義View注意事項

11) 現在下載速度很慢,試從網絡協議的角度分析原因,並優化(提示:網絡的5層都可以涉及)。

12) Https請求慢的解決辦法(提示:DNS,攜帶數據,直接訪問IP)

13) 如何保持應用的穩定性

14) RecyclerView和ListView的性能對比

15) ListView的優化

16) RecycleView優化

17) View渲染

18) Bitmap如何處理大圖,如一張30M的大圖,如何預防OOM

19) java中的四種引用的區別以及使用場景

20) 強引用置爲null,會不會被回收?

(七)NDK、jni、Binder、AIDL、進程通信有關**

1) 請介紹一下NDK

2) 什麼是NDK庫?

3) jni用過嗎?

4) 如何在jni中註冊native函數,有幾種註冊方式?

5) Java如何調用c、c++語言?

6) jni如何調用java層代碼?

7) 進程間通信的方式?

8) Binder機制

9) 簡述IPC?

10) 什麼是AIDL?

11) AIDL解決了什麼問題?

12) AIDL如何使用?

13) Android 上的 Inter-Process-Communication 跨進程通信時如何工作的?

14) 多進程場景遇見過麼?

15) Android進程分類?

16) 進程和 Application 的生命週期?

17) 進程調度

18) 談談對進程共享和線程安全的認識

19) 談談對多進程開發的理解以及多進程應用場景

20) 什麼是協程?

(八)framework層、ROM定製、Ubuntu、Linux之類的問題**

1) java虛擬機的特性

2) 談談對jvm的理解

3) JVM內存區域,開線程影響哪塊內存

4) 對Dalvik、ART虛擬機有什麼瞭解?

5) Art和Dalvik對比

6) 虛擬機原理,如何自己設計一個虛擬機(內存管理,類加載,雙親委派)

7) 談談你對雙親委派模型理解

8) JVM內存模型,內存區域

9) 類加載機制

10) 談談對ClassLoader(類加載器)的理解

11) 談談對動態加載(OSGI)的理解

12) 內存對象的循環引用及避免

13) 內存回收機制、GC回收策略、GC原理時機以及GC對象

14) 垃圾回收機制與調用System.gc()區別

15) Ubuntu編譯安卓系統

16) 系統啓動流程是什麼?(提示:Zygote進程 –> SystemServer進程 –> 各種系統服務 –> 應用進程)

17) 大體說清一個應用程序安裝到手機上時發生了什麼

18) 簡述Activity啓動全部過程

19) App啓動流程,從點擊桌面開始

20) 邏輯地址與物理地址,爲什麼使用邏輯地址?

21) Android爲每個應用程序分配的內存大小是多少?

22) Android中進程內存的分配,能不能自己分配定額內存?

23) 進程保活的方式

24) 如何保證一個後臺服務不被殺死?(相同問題:如何保證service在後臺不被kill?)比較省電的方式是什麼?

25) App中喚醒其他進程的實現方式

(九)算法

1) 排序算法有哪些?

2) 最快的排序算法是哪個?

3) 手寫一個冒泡排序

4) 手寫快速排序代碼

5) 快速排序的過程、時間複雜度、空間複雜度

6) 手寫堆排序

7) 堆排序過程、時間複雜度及空間複雜度

8) 寫出你所知道的排序算法及時空複雜度,穩定性

9) 二叉樹給出根節點和目標節點,找出從根節點到目標節點的路徑

10) 給阿里2萬多名員工按年齡排序應該選擇哪個算法?

11) GC算法(各種算法的優缺點以及應用場景)

12) 蟻羣算法與蒙特卡洛算法

13) 子串包含問題(KMP 算法)寫代碼實現

14) 一個無序,不重複數組,輸出N個元素,使得N個元素的和相加爲M,給出時間複雜度、空間複雜度。手寫算法

15) 萬億級別的兩個URL文件A和B,如何求出A和B的差集C(提示:Bit映射->hash分組->多文件讀寫效率->磁盤尋址以及應用層面對尋址的優化)

16) 百度POI中如何試下查找最近的商家功能(提示:座標鏡像+R樹)。

17) 兩個不重複的數組集合中,求共同的元素。

18) 兩個不重複的數組集合中,這兩個集合都是海量數據,內存中放不下,怎麼求共同的元素?

19) 一個文件中有100萬個整數,由空格分開,在程序中判斷用戶輸入的整數是否在此文件中。說出最優的方法

20) 一張Bitmap所佔內存以及內存佔用的計算

21) 2000萬個整數,找出第五十大的數字?

22) 燒一根不均勻的繩,從頭燒到尾總共需要1個小時。現在有若干條材質相同的繩子,問如何用燒繩的方法來計時一個小時十五分鐘呢?

23) 求1000以內的水仙花數以及40億以內的水仙花數

24) 5枚硬幣,2正3反如何劃分爲兩堆然後通過翻轉讓兩堆中正面向上的硬8幣和反面向上的硬幣個數相同

25) 時針走一圈,時針分針重合幾次

26) N*N的方格紙,裏面有多少個正方形

27) x個蘋果,一天只能吃一個、兩個、或者三個,問多少天可以吃完?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章