這裏講的是大公司需要用到的一些高端Android技術,這裏專門整理了一個文檔,希望大家都可以看看。這些題目有點技術含量,需要好點時間去研究一下的。
爲此我吧這些知識整理成了一個983的PDF,從基礎到進階。含有BATJ.字節跳動面試專題,算法專題,高端技術專題,混合開發專題,java面試專題,Android,Java小知識,到性能優化.線程.View.OpenCV.NDK等應有盡有。還有輔之相關的視頻+學習筆記
(更多完整項目下載。未完待續。源碼。圖文知識後續上傳github。)
可以點擊關於我聯繫我獲取完整PDF
(VX:×××)一.圖片
1、圖片庫對比
2、LRUCache原理
LruCache
是個泛型類,主要原理是:把最近使用的對象用強引用存儲在LinkedHashMap
中,當緩存滿時,把最近最少使用的對象從內存中移除,並提供get/put方法完成緩存的獲取和添加。LruCache
是線程安全的,因爲使用了synchronized關鍵字。
當調用put()方法,將元素加到鏈表頭,如果鏈表中沒有該元素,大小不變,如果沒有,需調用trimToSize方法判斷是否超過最大緩存量,trimToSize()方法中有一個while(true)死循環,如果緩存大小大於最大的緩存值,會不斷刪除LinkedHashMap中隊尾的元素,即最少訪問的,直到緩存大小小於最大緩存值。當調用LruCache的get方法時,LinkedHashMap會調用recordAccess方法將此元素加到鏈表頭部。
3、圖片加載原理
4、自己去實現圖片庫,怎麼做?
5、Glide源碼解析
1)Glide.with(context)創建了一個RequestManager
,同時實現加載圖片與組件生命週期綁定:在Activity上創建一個透明的ReuqestManagerFragment
加入到FragmentManager
中,通過添加的Fragment感知Activty
`Fragment的生命週期。因爲添加到Activity中的Fragment會跟隨Activity的生命週期。在
RequestManagerFragment中的相應生命週期方法中通過
liftcycle傳遞給在
lifecycle中註冊的
LifecycleListener`
2)RequestManager.load(url)
創建了一個RequestBuilder<T>
對象 T可以是Drawable
對象或是ResourceType
等
3 )RequestBuilder.into(view)
-->into(glideContext.buildImageViewTarget(view, transcodeClass))
返回的是一個DrawableImageViewTarget
, Target用來最終展示圖片的,buildImageViewTarget
-->ImageViewTargetFactory.buildTarget()
根據傳入class參數不同構建不同的Target對象,這個Class是根據構建Glide時是否調用了asBitmap()
方法,如果調用了會構建出BitmapImageViewTarget
,否則構建的是GlideDrawableImageViewTarget
對象。
-->GenericRequestBuilder.into(Target)
,該方法進行了構建Request,並用RequestTracker.runRequest()
Request request = buildRequest(target);//構建Request對象,Request是用來發出加載圖片的,它調用了buildRequestRecursive()方法以,內部調用了GenericRequest.obtain()方法
target.setRequest(request);
lifecycle.addListener(target);
requestTracker.runRequest(request);//判斷Glide當前是不是處於暫停狀態,若不是則調用Request.begin()方法來執行Request,否則將Request添加到待執行隊列裏,等暫停態解除了後再執行
-->GenericRequest.begin()
4)onSizeReady()·--> Engine.load(signature
, width
,height
, dataFetcher
, loadProvider
, transformation
, transcoder
,
priority, isMemoryCacheable
,diskCacheStrategy
, this) --> a)先構建EngineKey
; b)loadFromCache
從緩存中獲取EngineResource
,如果緩存中獲取到cache就調用cb.onResourceReady(cached)
; c)如果緩存中不存在調用loadFromActiveResources
從active中獲取,如果獲取到就調用cb.onResourceReady(cached)
;d)如果active中也不存在,調用EngineJob.start(EngineRunnable)
, 從而調用decodeFromSource()
/decodeFromCache()
-->如果是調用decodeFromSource()
-->ImageVideoFetcher.loadData()
-->HttpUrlFetcher()
調用HttpUrlConnection
進行網絡請求資源-->得於InputStream()
後,調用decodeFromSourceData()
-->loadProvider.getSourceDecoder().decode()
方法解碼-->GifBitmapWrapperResourceDecoder.decode()
-->decodeStream()
先從流中讀取2個字節判斷是GIF還是普通圖,若是GIF調用decodeGifWrapper()
來解碼,若是普通靜圖則調用decodeBitmapWrapper()
來解碼-->bitmapDecoder.decode()
6、Glide使用什麼緩存?
1) 內存緩存:LruResourceCache(memory)+
弱引用activeResources
Map<Key, WeakReference
<EngineResource
<?>>> activeResources
正在使用的資源,當acquired變量大於0,說明圖片正在使用,放到activeResources
弱引用緩存中,經過release()後,acquired=0,說明圖片不再使用,會把它放進LruResourceCache
中
2)磁盤緩存:DiskLruCache
,這裏分爲Source(原始圖片)和Result(轉換後的圖片)
第一次獲取圖片,肯定網絡取,然後存active\disk中,再把圖片顯示出來,第二次讀取相同的圖片,並加載到相同大小的imageview
中,會先從memory中取,沒有再去active中獲取。如果activity執行到onStop
時,圖片被回收,active中的資源會被保存到memory中,active中的資源被回收。當再次加載圖片時,會從memory中取,再放入active中,並將memory中對應的資源回收。
之所以需要activeResources
,它是一個隨時可能被回收的資源,memory的強引用頻繁讀寫可能造成內存激增頻繁GC
,而造成內存抖動。資源在使用過程中保存在activeResources
中,而activeResources
是弱引用,隨時被系統回收,不會造成內存過多使用和泄漏。
7、Glide內存緩存如何控制大小?
Glide內存緩存最大空間(maxSize)=每個進程可用最大內存0.4(低配手機是 每個進程可用最大內存0.33)
磁盤緩存大小是250MB int DEFAULT_DISK_CACHE_SIZE = 250 1024 1024;
二網絡和安全機制
1.網絡框架對比和源碼分析
2.自己去設計網絡請求框架,怎麼做?
3.okhttp源碼
4.網絡請求緩存處理,okhttp如何處理網絡緩存的;
(1)網絡緩存優先考慮強制緩存,再考慮對比緩存
- 首先判斷強制緩存中的數據的是否在有效期內。如果在有效期,則直接使用緩存。如果過了有效期,則進入對比緩存。
- 在對比緩存過程中,判斷ETag是否有變動,如果服務端返回沒有變動,說明資源未改變,使用緩存。如果有變動,判斷Last-Modified。
- 判斷Last-Modified,如果服務端對比資源的上次修改時間沒有變化,則使用緩存,否則重新請求服務端的數據,並作緩存工作。
(2)okhttp緩存
開啓使用Okhttp的緩存其實很簡單,只需要給OkHttpClient
對象設置一個Cache對象即可,創建一個Cache時指定緩存保存的目錄和緩存最大的大小即可。
//新建一個cache,指定目錄爲外部目錄下的okhttp_cache目錄,大小爲100M
Cache cache = new Cache(new File(Environment.getExternalStorageDirectory() + "/okhttp_cache/"), 100 * 1024 * 1024);
//將cache設置到OkHttpClient中,這樣緩存就開始生效了。
OkHttpClient client = new OkHttpClient.Builder().cache(cache).build();
相關的類有:
1)CacheControl( HTTP中的Cache-Control和Pragma緩存控制):指定緩存規則
2)Cache(緩存類)
3)DiskLruCache(文件化的LRU緩存類)
(1)讀取緩存:先獲限OkHttpClient
的Cache緩存對象,就是上面創建OkHttpClient
設置的Cahce
; 傳Request請求到Cache的get方法查找緩存響應數據Response;構造一個緩存策略,再調用它的get去決策使用網絡請求還是緩存響應。若使用緩存,它的cacheResponse
不爲空,networkRequest
爲空,用緩存構造響應直接返回。若使用請求,則cacheResponse
爲空,networkRequest
不爲空,開始網絡請求流程。
Cache的get獲取緩存方法,計算request的key值(請求url進行md5加密),根據key值去DisLruCache查找是否存在緩存內容,存則則創建繪存Entry實體。ENTRY_METADATA代表響應頭信息,ENTRY_BODY代表響應體信息。如果緩存存在,在指定目錄下會有兩個文件**.0 ***.1分別存儲某個請求緩存響應頭和響應體信息。
CacheStrategy的get方法:
- 若緩存響應爲空
- 請求是https但緩存響應沒有握手信息;
- 請求和緩存響應都是不可緩存的;
- 請求是onCache,並且又包含if-Modified-Since或If-None-Match則不使用緩存; 再計算請求有效時間是否符合響應的過期時間,若響應在有效範圍內,則緩存策略使用緩存,否則創建一個新的有條件的請求,返回有條件的緩存策略。
(2)存儲緩存流程:從HttpEngine
的readResponse()
發送請求開始,判斷hasBody(userResponse)
,如果緩存的話,maybeCache()
緩存響應頭信息,unzip(cacheWritingResponse(storeRequest, userResponse))
緩存響應體。
5.從網絡加載一個10M的圖片,說下注意事項
6.TCP的3次握手和四次揮手
7.TCP與UDP的區別
8.TCP與UDP的應用*
9.HTTP協議
10.HTTP1.0與2.0的區別
11.HTTP報文結構
12.HTTP與HTTPS的區別以及如何實現安全性
13.如何驗證證書的合法性?
14.https中哪裏用了對稱加密,哪裏用了非對稱加密,對加密算法(如RSA)等是否有了解?
15.client如何確定自己發送的消息被server收到?
16.談談你對WebSocket的理解
17.WebSocket與socket的區別
18.談談你對安卓簽名的理解。
19.請解釋安卓爲啥要加簽名機制?**
20.視頻加密傳輸
21.App 是如何沙箱化,爲什麼要這麼做?
22.權限管理系統(底層的權限是如何進行 grant 的)?
三.數據庫
1.sqlite升級,增加字段的語句
2.數據庫框架對比和源碼分析
3.數據庫的優化
4.數據庫數據遷移問題
四.算法
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所佔內存以及內存佔用的計算
一張圖片(bitmap)佔用的內存影響因素:圖片原始長、寬,手機屏幕密度,圖片存放路徑下的密度,單位像素佔用字節數
bitmapSize=圖片長度(inTargetDensity手機的density / inDensity圖片存放目錄的density)寬度(手機的inTargetDensity / inDensity目標存放目錄的density)單位像素佔用的字節數(圖片長寬單位是像素)
1)圖片長寬單位是像素:單位像素字節數由其參數BitmapFactory.Options.inPreferredConfig
變量決定,它是Bitmap.Config類型,包括以下幾種值:ALPHA_8圖片只有alpha值,佔用一個字節;ARGB_4444
一個像素佔用2個字節,A\R\G\B各佔4bits
;ARGB_8888
一個像素佔用4個字節,A\R\G\B各佔8bits
(高質量圖片格式,bitmap默認格式);ARGB_565
一個像素佔用2字節,不支持透明和半透明,R佔5bit
, Green佔6bit
, Blue佔用5bit
. 從Android4.0
開始該項無效。
2)inTargetDensity
手機的屏幕密度(跟手機分辨率有關係)
inDensity
原始資源密度(mdpi:160
; hdpi:240
; xhdpi:320
; xxhdpi:480
; xxxhdpi:640
)
當Bitmap對象在不使用時,應該先調用recycle(),再將它設置爲null,雖然Bitmap在被回收時可通過BitmapFinalizer
來回收內存。但只有系統垃圾回收時纔會回收。Android4.0
之前,Bitmap內存分配在Native堆中,Android4.0
開始,Bitmap的內存分配在dalvik
堆中,即Java堆中,調用recycle()並不能立即釋放Native內存。
21. 2000萬個整數,找出第五十大的數字?
22.燒一根不均勻的繩,從頭燒到尾總共需要1個小時。現在有若干條材質相同的繩子,問如何用燒繩的方法來計時一個小時十五分鐘呢?
23.求1000以內的水仙花數以及40億以內的水仙花數
24. 5枚硬幣,2正3反如何劃分爲兩堆然後通過翻轉讓兩堆中正面向上的硬8幣和反面向上的硬幣個數相同
25.時針走一圈,時針分針重合幾次
26*.NN的方格紙,裏面有多少個正方形
27.x個蘋果,一天只能吃一個、兩個、或者三個,問多少天可以吃完?
五.插件化、模塊化、組件化、熱修復、增量更新、Gradle
1.對熱修復和插件化的理解
2.插件化原理分析
3.模塊化實現(好處,原因)
4.熱修復,插件化
5.項目組件化的理解
6.描述清點擊 Android Studio 的 build 按鈕後發生了什麼
六.架構設計和設計模式
1.談談你對Android設計模式的理解
2.MVC MVP MVVM原理和區別
3.你所知道的設計模式有哪些?
4.項目中常用的設計模式
5.手寫生產者/消費者模式
6.寫出觀察者模式的代碼
7.適配器模式,裝飾者模式,外觀模式的異同?
8.用到的一些開源框架,介紹一個看過源碼的,內部實現過程。
9.談談對RxJava的理解
RxJava
是基於響應式編程,基於事件流、實現異步操(類似於Android中的AsyncTask
、Handler
作用)作的庫,基於事件流的鏈式調用,使得RxJava
邏輯簡潔、使用簡單。RxJava
原理是基於一種擴展的觀察者模式,有四種角色:被觀察者Observable 觀察者Observer 訂閱subscribe 事件Event。RxJava
原理可總結爲:被觀察者Observable通過訂閱(subscribe)按順序發送事件(Emitter)給觀察者(Observer), 觀察者按順序接收事件&作出相應的響應動作。
RxJava
中的操作符:
1)defer():直到有觀察者(Observer)訂閱時,纔會動態創建被觀察者對象(Observer)&發送事件,通過Observer工廠方法創建被觀察者對象,每次訂閱後,都會得到一個剛創建的最新的Observer對象,可以確保Observer對象裏的數據是最新的。defer()方法只會定義Observable對象,只有訂閱操作纔會創建對象。
Observable<T> observable = Observable.defer(new Callable<ObservableSource<? extends T>>() {
@Override
public ObservableSource<? extends T> call() throws Exception {
return Observable.just();
}
}
2)timer() 快速創建一個被觀察者(Observable),延遲指定時間後,再發送事件
Observable.timer(2, TimeUnit.SECONDS)//也可以自定義線程timer(long, TimeUnit, Scheduler)
.subscribe(new Observer<Long>() {
@Override
public void onSubscribe(Disposable d) {
}
...
});
3) interval() intervalRange() 快速創建一個被觀察者對象(Observable),每隔指定時間就發送事件
//interval三個參數,參數1:第一次延遲時間 參數2:間隔時間數字 參數3:時間單位
Observable.interval(3, 1, TimeUnit.SECONDS).subscribe();
//intervalRange五個參數,參數1:事件序列起始點 參數2:事件數量 參數3:第一次延遲時間 參數4:間隔時間數字 參數5:時間單位
Observable.intervalRange(3, 10, 2, 1, TimeUnit.SECONDS).subscribe();
RxJava的功能與原理實現
10.Rxjava發送事件步驟:
1)創建被觀察者對象Observable&定義需要發送的事件
Observable.create(new ObservableOnSubscribe<T>(){
@Override
public void subscribe(ObservableEmitter<T> emitter) throws Exception {
//定義發送事件的行爲
}
});
Observable.create()方法實際創建了一個ObservableCreate
對象,它是Observable的子類,傳入一個ObservableOnSubscrib
e對象,複寫了發送事件行爲的subscribe()方法。
2)創建觀察者對象Observer&定義響應事件的行爲
Observer observer = new Observer<T>() {
@Override
public void onSubscribe(Disposable d){//Disposable對象可用於結束事件
//默認最先調用
}
@Override
public void onNext(T t){
}
@Override
public void onError(Throwable d){
}
@Override
public void onComplete(){
}
}
3)通過subscribe()方法使觀察者訂閱被觀察者
Observable.subscribe(Observer observer);//實際調用的是ObservableCreate.subscribeActual()方法,具體實現如下
protected void subscribeActual(Observer<? super T> observer) {
// 1. 創建1個CreateEmitter對象用於發射事件(封裝成1個Disposable對象)
CreateEmitter<T> parent = new CreateEmitter<T>(observer);
// 2. 調用觀察者(Observer)的onSubscribe()
observer.onSubscribe(parent);
try {
// 3. 調用source對象的(ObservableOnSubscribe對象)subscribe()
source.subscribe(parent);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
parent.onError(ex);
}
}
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中喚醒其他進程的實現方式
(更多完整項目下載。未完待續。源碼。圖文知識後續上傳github。)
可以點擊關於我聯繫我獲取完整PDF
(VX:×××)