溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

被問到Glide 源碼等突破性問題,不好意思我都會

發(fā)布時間:2020-07-02 22:32:22 來源:網(wǎng)絡 閱讀:301 作者:Android丶VG 欄目:移動開發(fā)

之前在一次面試中被問到數(shù)據(jù)庫.網(wǎng)絡請求.IntentService. view 繪制.內存泄漏.OOM.動畫框架.自定義 view.Glide 源碼.屬性動畫等等一系列的問題,雖然都答上來了,但是還是有一些細節(jié)性的東西沒有注意得到。

回來以后吧很多知識整理成了一份PDF,還是比較全面的
(^▽^)
從基礎到進階。含有BATJ.字節(jié)跳動面試專題,算法專題,高端技術專題,混合開發(fā)專題,java面試專題,Android,Java小知識,到性能優(yōu)化.線程.View.OpenCV.NDK等應有盡有。還有輔之相關的視頻+學習筆記
被問到Glide 源碼等突破性問題,不好意思我都會

(更多完整項目下載。未完待續(xù)。源碼。圖文知識后續(xù)上傳github。)
可以點擊關于我聯(lián)系我獲取完整PDF
(VX:mm14525201314)

1.數(shù)據(jù)庫的操作類型有哪些,如何導入外部數(shù)據(jù)庫?

讀懂題目。如果碰到問題比較模糊的時候可以適當問問面試官。

配合面試官來面試:面試是一個相互了解的過程,要充分利用面試的題目和時間把自己的能力和技術展現(xiàn)出來,面試官能夠看到你的真實技術。

1)使用數(shù)據(jù)庫的方式有哪些?
  • openOrCreateDatabase(String path);
  • 繼承SqliteOpenHelper類對數(shù)據(jù)庫及其版本進行管理(onCreate,onUpgrade)
    當在程序當中調用這個類的方法getWritableDatabase()或者getReadableDatabase();的時候才會打開數(shù)據(jù)庫。如果當時沒有數(shù)據(jù)庫文件的時候,系統(tǒng)就會自動生成一個數(shù)據(jù)庫。
2)操作的類型:增刪改查CRUD

直接操作SQL語句SQliteDatabase.execSQL(sql);
面向對象的操作方式SQLiteDatabase.insert(table, nullColumnHack, ContentValues);

如何導入外部數(shù)據(jù)庫?

一般外部數(shù)據(jù)庫文件可能放在SD卡或者res/raw或者assets目錄下面。

寫一個DBManager的類來管理,數(shù)據(jù)庫文件搬家,先把數(shù)據(jù)庫文件復制到”/data/data/包名/databases/”目錄下面,然后通過db.openOrCreateDatabase(db文件),打開數(shù)據(jù)庫使用。
我上一個項目就是這么做的,由于app上架之前就有一些初始數(shù)據(jù)需要內置,也會碰到數(shù)據(jù)的升級等問題,我是這么做的…… 同時我碰到最有意思的問題就是關于數(shù)據(jù)庫并發(fā)操作的問題,比如:多線程操作數(shù)據(jù)庫的時候,我采取的是封裝使用互斥鎖來解決……

2.是否使用過本地廣播,和全局廣播有什么差別?

引入本地廣播的機制是為了解決安全性的問題:

1) 正在發(fā)送的廣播不會脫離應用程序,比用擔心app的數(shù)據(jù)泄露;
2) 其他的程序無法發(fā)送到我的應用程序內部,不擔心安全漏洞。(比如:如何做一個殺不死的服務---監(jiān)聽火的app 比如微信、友盟、極光的廣播,來啟動自己。)
3) 發(fā)送本地廣播比發(fā)送全局的廣播高效。(全局廣播要維護的廣播集合表 效率更低。全局廣播,意味著可以跨進程,就需要底層的支持。)

本地廣播不能用靜態(tài)注冊。----靜態(tài)注冊:可以做到程序停止后還能監(jiān)聽。
使用:

  • 注冊:
    LocalBroadcastManager.getInstance(this).registerReceiver(new XXXBroadCastReceiver(), new IntentFilter(action));
  • 取消注冊:
    LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver)
3.是否使用過 IntentService,作用是什么, AIDL 解決了什么問題?

如果有一個任務,可以分成很多個子任務,需要按照順序來完成,如果需要放到一個服務中完成,那么使用IntentService是最好的選擇。

一般我們所使用的Service是運行在主線程當中的,所以在service里面編寫耗時的操作代碼,則會卡主線程會ANR。為了解決這樣的問題,谷歌引入了IntentService.

IntentService的優(yōu)點:
(1) 它創(chuàng)建一個獨立的工作線程來處理所有一個一個intent。
(2) 創(chuàng)建了一個工作隊列,來逐個發(fā)送intent給onHandleIntent()
(3) 不需要主動調用stopSelf()來結束服務,因為源碼里面自己實現(xiàn)了自動關閉。
(4) 默認實現(xiàn)了onBind()返回的null。
(5) 默認實現(xiàn)的onStartCommand()的目的是將intent插入到工作隊列。

總結: 使用IntentService的好處有哪些。首先,省去了手動開線程的麻煩;第二,不用手動停止service;第三,由于設計了工作隊列,可以啟動多次---startService(),但是只有一個service實例和一個工作線程。一個一個熟悉怒執(zhí)行。

AIDL 解決了什么問題?
AIDL的全稱:Android Interface Definition Language,安卓接口定義語言。
由于Android系統(tǒng)中的進程之間不能共享內存,所以需要提供一些機制在不同的進程之間進行數(shù)據(jù)通信。

遠程過程調用: RPC—Remote Procedure Call。 安卓就是提供了一種IDL的解決方案來公開自己的服務接口。AIDL:可以理解為雙方的一個協(xié)議合同。雙方都要持有這份協(xié)議---文本協(xié)議 xxx.aidl文件(安卓內部編譯的時候會將aidl協(xié)議翻譯生成一個xxx.java文件---代理模式:Binder驅動有關的,Linux底層通訊有關的。)
在系統(tǒng)源碼里面有大量用到aidl,比如系統(tǒng)服務。
電視機頂盒系統(tǒng)開發(fā)。你的服務要暴露給別的開發(fā)者來使用。

講解Binder機制。

4.Activity、 Window、 View 三者的差別, fragment 的特點?

Activity、 Window、 View 三者如何協(xié)同顯示界面的。---考點:顯示的過程(view 繪制流程)源碼的熟悉度。

Activity剪窗花的人(控制的);Window窗戶(承載的一個模型);View窗花(要顯示的視圖View);LayoutInflater剪刀---將布局(圖紙)剪成窗花。
(Alt+方向箭頭)

fragment 的特點?(你用fragment有沒有領略到一些樂趣,或者有沒有踩過什么坑?)

fragment的設計主要是把Activity界面包括其邏輯打碎成很多個獨立的模塊,這樣便于模塊的重用和更靈活地組裝呈現(xiàn)多樣的界面。

  • Fragment可以作為Activity界面的一個部分組成;
  • 可以在一個Activity里面出現(xiàn)多個Fragment,并且一個fragment可以在多個Activity中使用;
  • 在Activity運行中,可以動態(tài)地添加、刪除、替換Fragment。
  • Fragment有自己的生命周期的,可以響應輸入事件。

踩過的坑:

  • 重疊;
  • 注解newAPI(兼容包解決);
  • Setarguement()初始化數(shù)據(jù);
  • 不能在onsave...()方法后,commit;
  • 入棧出棧問題; --事務。像Activity跳轉一樣的效果,同時返回的時候還能回到之前的頁面(fragment)并且狀態(tài)都還在。replace(f1,f2)嚴重影響生命周期:add()+show+hide
5. 低版本 SDK 實現(xiàn)高版本 api

幾種情況:

1) 一般很多高版本的新的API都會在兼容包里面找到替代的實現(xiàn)。比如fragment。
Notification,在v4兼容包里面有NotificationCompat類。5.0+出現(xiàn)的backgroundTint,minSdk小于5.0的話會包檢測錯誤,v4兼容包DrawableCompat類。
2) 沒有替代實現(xiàn)就自己手動實現(xiàn)。比如:控件的水波紋效果—第三方實現(xiàn)。
或者直接在低版本去除這個效果。
3)補充: 如果設置了minSDK但是代碼里面使用了高版本的API,會出現(xiàn)檢測錯誤。需要在代碼里面使用聲明編譯檢測策略,比如:@SuppressLint@TargetApi注解提示編譯器編譯的規(guī)則。@SuppressLint是忽略檢測;@TargetApi=23,會根據(jù)你函數(shù)里面使用的API,嚴格地匹配SDK版本,給出相應的編譯錯誤提示。
4)為了避免位置的錯誤,最好不要使用廢棄api。(一般情況下不會有兼容性問題,后面可能會隨時刪除這個API方法;性能方面的問題。)

6. launch mode 應用場景

:先進后出
標準模式
SingleTop:使用場景:瀏覽器的書簽;通訊消息聊天界面。
SingleTask:使用場景:某個Activity當做主界面的時候。
SingleInstance:使用場景:比如瀏覽器BrowserActivity很耗內存,很多app都會要調用它,這樣就可以把該Activity設置成單例模式。比如:鬧鐘鬧鈴。

7.view 繪制流程

Measure: 測量,測量自己。如果是ViewGroup就需要測量里面的所有childview.
測量的結果怎么辦?setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState), heightSizeAndState);設置自己的大小。
Layout: 擺放,把自己擺放在哪個位置。如果是ViewGroup就需要發(fā)放里面的所有childview.
怎么去具體擺放呢?
Draw:繪制

  /*
         * Draw traversal performs several drawing steps which must be executed
         * in the appropriate order:
         *
         *      1. Draw the background
         *      2. If necessary, save the canvas' layers to prepare for fading
         *      3. Draw view's content
         *      4. Draw children
         *      5. If necessary, draw the fading edges and restore layers
         *      6. Draw decorations (scrollbars for instance)
         */
8. 什么情況導致內存泄漏

1) 什么是內存泄漏:最好解釋清楚GC垃圾回收機制以及概念GC Root。
2) 為什么會有內存泄漏:因為內存泄漏是屬于人為的失誤造成的。而且面向對象開發(fā)關系復雜、多線程的關系,很容易出現(xiàn)引用層級關系很深以及很混亂。
3) 什么情況容易導致內存泄漏:
4) 如何解決內存泄漏

9. ANR 定位和修正

可以通過查看/data/anr/traces.txt查看ANR信息。
根本原因是:主線程被卡了,導致應用在5秒時間未響應用戶的輸入事件。

很多種ANR錯誤出現(xiàn)的場景:

  • 主線程當中執(zhí)行IO/網(wǎng)絡操作,容易阻塞。
  • 主線程當中執(zhí)行了耗時的計算。----自定義控件的時候onDraw方法里面經常這么做。
    (同時聊一聊自定義控件的性能優(yōu)化:在onDraw里面創(chuàng)建對象容易導致內存抖動---繪制動作會大量不斷調用,產生大量垃圾對象導致GC很頻繁就造成了內存抖動。)內存抖動就容易造成UI出現(xiàn)掉幀卡頓的問題
  • BroadCastReceiver沒有在10秒內完成處理。
  • BroadCastReceiveronReceived代碼中也要盡量減少耗時的操作,建議使用IntentService處理。
  • Service執(zhí)行了耗時的操作,因為service也是在主線程當中執(zhí)行的,所以耗時操作應該在service里面開啟子線程來做。
  • 使用AsyncTask處理耗時的IO等操作。
  • 使用Thread或者HandlerThread時,使用Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)或者java.lang.Thread.setPriority (int priority)設置優(yōu)先級為后臺優(yōu)先級,這樣可以讓其他的多線程并發(fā)消耗CPU的時間會減少,有利于主線程的處理。
  • Activity的onCreateonResume回調中盡量耗時的操作。
10.什么情況導致 oom

OOM產生的原因:內存不足,
android系統(tǒng)為每一個應用程序都設置了一個硬性的條件:DalvikHeapSize最大閥值64M/48M/24M.如果你的應用程序內存占用接近這個閥值,此時如果再嘗試內存分配的時候就會造成OOM。

  • 內存泄露多了就容易導致OOM
  • 大圖的處理。壓縮圖片。平時開發(fā)就要注意對象的頻繁創(chuàng)建和回收。
  • 可以適當?shù)臋z測:ActivityManager.getMemoryClass()可以用來查詢當前應用的HeapSize閥值??梢酝ㄟ^命名adb shellgetProp | grep dalvik.vm.heapxxxlimit查看。

如何避免內存泄露:
1)減小對象的內存占用:

  • 使用更加輕量級的數(shù)據(jù)結構
    考慮適當?shù)那闆r下替代HashMap等傳統(tǒng)數(shù)據(jù)結構而使用安卓專門為手機研發(fā)的數(shù)據(jù)結構類ArrayMap/SparseArray。SparseLongMap/SparseIntMap/SparseBoolMap更加高效。
    HashMap.put(string,Object);Object o = map.get(string);會導致一些沒必要的自動裝箱和拆箱。
    • 適當?shù)谋苊庠赼ndroid中使用Enum枚舉,替代使用普通的static常量。(一般還是提倡多用枚舉---軟件的架構設計方面;如果碰到這個枚舉需要大量使用的時候就應該更加傾向于解決性能問題。)。
    • 較少Bitmap對象的內存占用。
      使用inSampleSize: 計算圖片壓縮比例進行圖片壓縮,可以避免大圖加載造成OOM;
      decodeformat:圖片的解碼格式選擇,ARGB_8888/RGB_565/ARGB_4444/ALPHA_8,還可以使用WebP
    • 使用更小的圖片
      資源圖片里面,是否存在還可以繼續(xù)壓縮的空間。

2)內存對象的重復利用:
使用對象池技術,
兩種:

自己寫;
利用系統(tǒng)既有的對象池機制。比如LRU(Last Recently Use)算法。

  • a.ListView/GridView源碼可以看到重用的情況ConvertView的復用。RecyclerViewRecycler源碼。
  • b.Bitmap的復用
    Listview等要顯示大量圖片。需要使用LRU緩存機制來復用圖片。
  • c. 避免在onDraw方法里面執(zhí)行對象的創(chuàng)建,要復用。避免內存抖動。
  • d 常見的java基礎問題---StringBuilder

3)避免對象的內存泄露
4)使用一些內存的優(yōu)化策略:看文檔

11.Android Service 與 Activity 之間通信的幾種方式

1)通過Binder
2)通過廣播

12.Android 各個版本 API 的區(qū)別

把幾個關鍵版本的特性記住:3.0/4.0、4.4、5.0、6.0/7.0

13.Requestlayout, onlayout, onDraw, DrawChild 區(qū)別與聯(lián)系

RequestLayout()方法: 會導致調用Measure()方法和layout()。將會根據(jù)標志位判斷是否需要onDraw();
onLayout()擺放viewGroup里面的子控件
onDraw()繪制視圖本身;(ViewGroup還需要繪制里面的所有子控件)
drawChild(): 重新回調每一個子視圖的draw方法。child.draw(canvas, this, drawingTime);

14.invalidate()和 postInvalidate() 的區(qū)別及使用

invalidate() 在主線程當中刷新;
postInvalidate()在子線程當中刷新;其實最終調用的就是invalidate,原理依然是通過工作線程向主線程發(fā)送消息這一機制。

public void postInvalidate() {
        postInvalidateDelayed(0);
    }
    public void postInvalidateDelayed(long delayMilliseconds) {
   // We try only with the AttachInfo because there's no point in invalidating
        // if we are not attached to our window
        final AttachInfo attachInfo = mAttachInfo;
        if (attachInfo != null) {
            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
        }
    }

    public void dispatchInvalidateDelayed(View view, long delayMilliseconds) {
        Message msg = mHandler.obtainMessage(MSG_INVALIDATE, view);
        mHandler.sendMessageDelayed(msg, delayMilliseconds);
    }
public void handleMessage(Message msg) {
            switch (msg.what) {
            case MSG_INVALIDATE:
                ((View) msg.obj).invalidate();
                break;
15.Android 動畫框架實現(xiàn)原理

傳統(tǒng)的動畫框架: View.startAnimation();
弊端: 移動后不能點擊。原因?跟實現(xiàn)機制有關系。
所有的透明度、旋轉、平移、縮放動畫,都是在view不斷刷新調用draw的情況下實現(xiàn)的。
調用的canvas.translate(xxx),canvas.scaleX(xxx)…. Xxx:matrix像素矩陣來控制動畫的數(shù)據(jù)。記得看源碼,結合多只縮放的demo看源碼。

16.Android 為每個應用程序分配的內存大小是多少?

看具體的手機平臺,常見的有:64M/32M等

17.LinearLayout 對比 RelativeLayout

性能對比: LinearLayout的性能要比RelativeLayout好。
因為RelativeLayout會測量兩次。而默認情況下(沒有設置weight)LinearLayout只會測量一次。

為什么RelativeLayout會測量兩次?首先RelativeLayout中的子view排列方式是基于彼此依賴的關系,而這個依賴可能和布局中view的順序無關,在確定每一個子view的位置的時候,就需要先給每一個子view排一下序。又因為RelativeLayout允許橫向和縱向相互依賴,所以需要橫向縱向分別進行一次排序測量。

18.優(yōu)化自定義 view

1) 減少在onDraw里面大量計算和對象創(chuàng)建和大量內存分配。
2) 應該盡量少用invalidate()次數(shù)。
3) view里面耗時的操作layout。減少requestLayout()避免讓UI系統(tǒng)重新遍歷整棵樹。Mearsure。
4) 如果你有一個很復雜的布局,不如將這個復雜的布局直接使用你自己的寫的ViewGroup來實現(xiàn)。減少了一個樹的層次關系 全部都是自己測量和layout,達到優(yōu)化的目的。(Facebook就經常這么干)

19.ContentProvider

提示:跨進程通信。進程之間進行數(shù)據(jù)交互共享。;源碼來一剁。

20.fragment 生命周期
21. volley 解析
22. Android Glide 源碼解析
23. Android 屬性動畫特性
24.如何保證一個后臺服務不被殺死,比較省電的方式是什么?
25. touch 事件傳遞流程
26. Handler、 Thread 和 HandlerThread 的差別
27.描述一次網(wǎng)絡請求的流程

請查看完整的PDF版
(更多完整項目下載。未完待續(xù)。源碼。圖文知識后續(xù)上傳github。)
可以點擊關于我聯(lián)系我獲取完整PDF
(VX:mm14525201314)

被問到Glide 源碼等突破性問題,不好意思我都會

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經查實,將立刻刪除涉嫌侵權內容。

AI