- 記錄自己面試和網上別人面試遇到的題目匯總。部分內容來自網絡钦椭,若有侵權請聯(lián)系我刪除
- 后續(xù)補充會先在 GitHub 上更新,歡迎補充
基礎知識
Service生命周期
-
service的生命周期分為兩種
生命周期
Android中的幾種動畫
補間動畫 :是對某個View進行一系列的動畫的操作碑诉,包括淡入淡出(Alpha)彪腔,縮放(Scale),平移(Translate)进栽,旋轉(Rotate)四種模式德挣。
幀動畫 : 將多張圖片組合起來進行播放,類似于早期電影的工作原理快毛,很多App的loading是采用這種方式
屬性動畫 : 屬性動畫不再僅僅是一種視覺效果了格嗅,而是一種不斷地對值進行操作的機制,并將值賦到指定對象的指定屬性上祸泪,可以是任意對象的任意屬性
從ActivityA跳轉到ActivityB的生命周期調用順序
-
打開ActivityA
onCreate(A) -> onStart(A) -> onResume(A)
-
打開ActivityB
onPause(A) -> onCreate(B) -> onStart(B) -> onResume(B) -> onStop(A)
-
回到ActivtyA
onPause(B) -> onRestart(A) -> onStart(A) -> onResume(A) -> onStop(B) -> onDestory(B)
HandlerThread的原理
- 釋義 HandlerThread 是可以創(chuàng)建帶有 looper 新線程的類
- HandlerThread 源碼解析
判斷處于主線程還是子線程
//1
Looper.getMainLooper() == Looper.myLooper();
//2
Looper.getMainLooper().getThread() == Thread.currentThread();
//3
Looper.getMainLooper().getThread().getId() == Thread.currentThread().getId();
設計模式
面向對象六大原則 | 單例模式 | Builder模式 |
原型模式 | 簡單工廠 | 工廠方法模式 |
抽象工廠模式 | 策略模式 | 狀態(tài)模式 |
責任鏈模式 | 解釋器模式 | 命令模式 |
觀察者模式 | 備忘錄模式 | 迭代器模式 |
模板方法模式 | 訪問者模式 | 中介者模式 |
代理模式 | 組合模式 | 適配器模式 |
裝飾模式 | 享元模式 | 外觀模式 |
onMeasure返回的兩個參數都有什么信息
- 兩個參數的意義: 父控件對View的寬高約束
- http://blog.csdn.net/xmxkf/article/details/51490283
View繪制流程
繪制過程:View的繪制過程是從ViewRoot 的 performTraversals 方法開始的吗浩, 它經過 measure、layout 和 draw 三個過程才能最終將一個 View 繪制出來没隘,其中 measure 用來測量 View 的寬高懂扼,layout 用來確定 view 在容器中的位置,draw 則負責將 view 繪制在屏幕上
-
流程圖
流程圖 -
鏈接
-
書籍參考
- 《Android開發(fā)藝術探索》第四章 P176
Activity的創(chuàng)建過程
ActivityManagerService -> </br>
ActivityStackSupervisor -> </br>
ActivityStack -> </br>
ActivityStackSupervisor -> </br>
ApplicationThread
- 鏈接
Handler
Handler 是Android類庫提供的用于接受、傳遞和處理消息或Runnable對象的處理類阀湿,它結合Message赶熟、MessageQueue和Looper類以及當前線程實現(xiàn)了一個消息循環(huán)機制,用于實現(xiàn)任務的異步加載和處理
-
主要用途
執(zhí)行定時任務 指定任務時間陷嘴,在某個具體時間或某個時間段后執(zhí)行特定的任務操作映砖,例如使用Handler提供的postDelayed(Runnable r,long delayMillis)方法指定在多久后執(zhí)行某項操作
線程間的通信 在執(zhí)行較為耗時的操作時,Handler負責將子線程中執(zhí)行的操作的結果傳遞到UI線程灾挨,然后UI線程再根據傳遞過來的結果進行相關UI元素的更新
-
Handler用法
示意圖 -
根據上面的圖片邑退,我們現(xiàn)在來解析一下異步消息處理機制
Message:消息體,用于裝載需要發(fā)送的對象
handler:它直接繼承自Object劳澄。作用是:在子線程中發(fā)送Message或者Runnable對象到MessageQueue中地技;在UI線程中接收、處理從MessageQueue分發(fā)出來的Message或者Runnable對象秒拔。發(fā)送消息一般使用Handler的sendMessage()方法莫矗,而發(fā)出去的消息經過處理后最終會傳遞到Handler的handlerMessage()方法中
MessageQueue:用于存放Message或Runnable對象的消息隊列。它由對應的Looper對象創(chuàng)建砂缩,并由Looper對象管理作谚。每個線程中都只會有一個MessageQueue對象
Looper:是每個線程中的MessageQueue的管家,循環(huán)不斷地管理MessageQueue接收和分發(fā)Message或Runnable的工作庵芭。調用Looper的loop()方法后妹懒,就會進入到一個無限循環(huán)中然后每當發(fā)現(xiàn)MessageQueue中存在一條消息,就會將它取出喳挑,并調用Handler的handlerMessage()方法彬伦。每個線程中也只會有一個Looper對象
Handler和Looper對象是屬于線程內部的數據滔悉,不過也提供與外部線程的訪問接口伊诵,Handler就是公開給外部線程的接口,用于線程間的通信回官。Looper是由系統(tǒng)支持的用于創(chuàng)建和管理MessageQueue的依附于一個線程的循環(huán)處理對象曹宴,而Handler是用于操作線程內部的消息隊列的,所以Handler也必須依附一個線程歉提,而且只能是一個線程
-
鏈接
解釋下Application類
-
定義
- 用于維護全局應用程序狀態(tài)的基礎類
- 代表應用程序的類笛坦,也屬于Android中的一個系統(tǒng)組件
- 繼承關系: 繼承自 ContextWarpper 類
-
Application 與 Context
- Activity、Service苔巨、Application 都是 Context 的子類版扩。Context 是一個抽象類,具體的實現(xiàn)是在 ContextImpl 類中侄泽。因此應用程序 APP 共用的 Context 數目公式為:
context數 = Service數 + Actvity數 + 1(Application 對應的 Context 實例)
- Activity、Service苔巨、Application 都是 Context 的子類版扩。Context 是一個抽象類,具體的實現(xiàn)是在 ContextImpl 類中侄泽。因此應用程序 APP 共用的 Context 數目公式為:
-
特點
-
實例創(chuàng)建方式:單例模式
- 每個 APP 運行時會首先自動創(chuàng)建 application 類并實例化 application 對象且只有一個(即 application 類是單例模式)
- 可以通過繼承 application 來實現(xiàn)自定義的 application 類
實例形式:全局模式礁芦,即不同組件都可以獲得 application 對象且都是同一個
生命周期:等于 APP 的生命周期.
-
-
連接
APK安裝過程
-
APK安裝的主要步驟
- 將 apk 文件復制到 /data/app/ 目錄下
- 解壓 apk ,拷貝文件, 創(chuàng)建應用的數據目錄
- 解析 apk 的AndroidManifinest.xml 文件
- 顯示快捷方式
-
鏈接
MultiDex工作原理分析和優(yōu)化方案
應用啟動流程分析
View的測量寬/高和最終寬/高有什么區(qū)別(另一種問法: view 的 getMeasuredWidth 和 getWidth 有什么區(qū)別)
在 View 的默認實現(xiàn)中 View 的測量寬/高和最終寬/高是相等的柿扣,只不過 測量寬高(getMeasureWidth/Height)是在 view 的 measure 過程中調用的肖方,而 view 的 最終寬高(getWidth/Height)是在 view 的 layout 過程中調用的;即兩者的賦值時機不同,測量寬高比最終寬高獲取的時機稍微早點;
-
在一般開發(fā)中這兩者的值是一樣的未状,但是也會存在特殊情況俯画,
-
比如在 view 的 layout 方法中:
public void layout(int l, int t, int r, int b){ super.layout(l, t, r+100, b+100); }
這個步驟就會導致測量寬高比最終寬高小 100px
另一種情況是在某些情況下 View 需要多次 measure 才能確定自己的測量寬高,在前幾次的測量寬高過程中得出的值可能和最終寬高的不一致司草,但最終來說:測量寬高和最終寬高相等
-
事件分發(fā)流程
-
Android事件分發(fā)流程
Activity(Windwos) -> ViewGroup -> View
流程圖說明- 對于
dispatchTouchEvent
,onTouchEvent
返回 true 就是自己消費了艰垂,返回 false 就傳到父View 的onTouchEvent
方法 - ViewGroup 想把事件分發(fā)給自己的
onTouchEvent
,需要在onInterceptTouchEvent
方法中返回 true 把事件攔截下來 - ViewGroup 的
onInterceptTouchEvent
默認不攔截,所以super.onInterceptTouchEvent() = false
- View(這里指沒有子View)沒有攔截器,所以 View 的
dispatchTouchEvent
的super.dispatchTouchEvent(event)
默認把事件分發(fā)給自己的onTouchEvent
- 對于
View的渲染機制
編譯打包的過程
- 等待補充
ANR的原理(源碼角度)
- 等待補充
屬性動畫的原理
- 等待補充
Android有多個資源文件夾材泄,應用在不同分辨率下是如何查找對應文件夾下的資源的,描述整個過程
- 等待補充
應用最多占可被分配多少內存
-> 進程數*16M
一個應用中有多少個 Window
有視圖的地方就有 Window吨岭,比如 Activity拉宗、Dialog、Toast辣辫、PopUpWindows旦事、菜單 等視圖都對應著一個window.
-
連接
為什么Dialog不能用Application的Context
Dialog初化始時是通過Context.getSystemServer 來獲取 WindowManager,而如果用Application或者Service的Context去獲取這個WindowManager服務的話急灭,會得到一個WindowManagerImpl的實例姐浮,這個實例里token也是空的。之后在Dialog的show方法中將Dialog的View(PhoneWindow.getDecorView())添加到WindowManager時會給token設置默認值還是null葬馋。
如果這個Context是Activity卖鲤,則直接返回Activity的mWindowManager,這個mWindowManager在Activity的attach方法被創(chuàng)建畴嘶,Token指向此Activity的Token蛋逾,mParentWindow為Activity的Window本身答案
那為什么一定要是Activity的Token呢?我想使用Token應該是為了安全問題窗悯,通過Token來驗證WindowManager服務請求方是否是合法的区匣。如果我們可以使用Application的Context,或者說Token可以不是Activity的Token蒋院,那么用戶可能已經跳轉到別的應用的Activity界面了亏钩,但我們卻可以在別人的界面上彈出我們的Dialog,想想就覺得很危險欺旧。
Android Activity 姑丑、 Window 、 View之間的關系
-
如圖
關于Android Force Close 出現(xiàn)的原因 以及解決方法
-
原因
- Error
- OOM , 內存溢出
- StackOverFlowError
- RuntimeException(比如空指針異常)
-
如何避免
- 可以實現(xiàn)Thread.UncaughtExceptionHandler接口的uncaughtException方法
哪些情況會出現(xiàn)內存泄漏辞友,如何解決
對于使用了Boardcast Receive栅哀、ContentObserver、File、Cursor昌屉、Stream钙蒙、Bitmap等資源的時候沒有銷毀。
解決方法 -> 應該在不使用的時候關閉或者注銷靜態(tài)內部類持有外部成員變量
解決方法 -> 可以使用若引用使用了 context 持有 Activity 導致 Activity無法釋放
解決方法 -> 使用 ApplicationContext集合中沒有使用的對象沒有及時 remove
handler 引起的內存泄漏
解決方法 -> 使用若引用持有 Activity等的 Context設置過的Listener沒有及時移除
解決方法 -> 在destory 里 設置 Listener 為 null
Android系統(tǒng)的架構
關于第三庫問題
Glide4.0源碼解析
otto源碼解析
Gilde怎么實現(xiàn)圓角圖
-
實現(xiàn)原理 利用
Transform
-
代碼示例
public class GlideRoundTransform extends BitmapTransformation { private static float radius = 0f; /** * 構造函數 默認圓角半徑 4dp * * @param context Context */ public GlideRoundTransform(Context context) { this(context, 4); } /** * 構造函數 * * @param context Context * @param dp 圓角半徑 */ public GlideRoundTransform(Context context, int dp) { super(context); radius = Resources.getSystem().getDisplayMetrics().density * dp; } @Override protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) { return roundCrop(pool, toTransform); } private static Bitmap roundCrop(BitmapPool pool, Bitmap source) { if (source == null) return null; Bitmap result = pool.get(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888); if (result == null) { result = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888); } Canvas canvas = new Canvas(result); Paint paint = new Paint(); paint.setShader(new BitmapShader(source, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP)); paint.setAntiAlias(true); RectF rectF = new RectF(0f, 0f, source.getWidth(), source.getHeight()); canvas.drawRoundRect(rectF, radius, radius, paint); return result; } @Override public String getId() { return getClass().getName() + Math.round(radius); } }