臨近雙11.有了這些中高端面試專題.大廠還會遠嗎?

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

爲此我吧這些知識整理成了一個983的PDF,從基礎到進階。含有BATJ.字節跳動面試專題,算法專題,高端技術專題,混合開發專題,java面試專題,Android,Java小知識,到性能優化.線程.View.OpenCV.NDK等應有盡有。還有輔之相關的視頻+學習筆記
臨近雙11.有了這些中高端面試專題.大廠還會遠嗎?

(更多完整項目下載。未完待續。源碼。圖文知識後續上傳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)存儲緩存流程:從HttpEnginereadResponse()發送請求開始,判斷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各佔4bitsARGB_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中的AsyncTaskHandler作用)作的庫,基於事件流的鏈式調用,使得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的子類,傳入一個ObservableOnSubscribe對象,複寫了發送事件行爲的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:×××)
臨近雙11.有了這些中高端面試專題.大廠還會遠嗎?

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