這是我近段時間收集的面試題,獻給打算年後找工做的同窗們。文中涉及的知識比較廣也可能比較零散,而且一些較爲基礎的知識我都略去了(好比Android四大組件是什麼這類問題),有些我附上了本身的理解,有些附上了詳細的相關文章連接。你們挑本身感興趣的內容查看便可,後期我也會繼續不斷補充。html
1.若是本身沒有配置android:ConfigChanges,這時默認讓系統處理,就會重建Activity,此時Activity的生命週期會走一遍。java
onSaveInstanceState() 與onRestoreIntanceState()
2.若是設置 android:configChanges="orientation|keyboardHidden|screenSize">
,此時Activity的生命週期不會重走一遍,Activity不會重建,只會回調onConfigurationChanged方法。android
(1)從Activity中啓動新的Activity時能夠直接mContext.startActivity(intent)
就好,git
(2)若是從其餘Context中啓動Activity則必須給intent設置Flag:程序員
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) ;
mContext.startActivity(intent);
複製代碼
整個應用程序的啓動過程要執行不少步驟,可是總體來看,主要分爲如下五個階段:github
一. :Launcher經過Binder進程間通訊機制通知ActivityManagerService,它要啓動一個Activity;
二.:ActivityManagerService經過Binder進程間通訊機制通知Launcher進入Paused狀態;
三.:Launcher經過Binder進程間通訊機制通知ActivityManagerService,它已經準備就緒進入Paused狀態,因而ActivityManagerService就建立一個新的進程,用來啓動一個ActivityThread實例,即將要啓動的Activity就是在這個ActivityThread實例中運行;
四. :ActivityThread經過Binder進程間通訊機制將一個ApplicationThread類型的Binder對象傳遞給ActivityManagerService,以便之後ActivityManagerService可以經過這個Binder對象和它進行通訊;
五 :ActivityManagerService經過Binder進程間通訊機制通知ActivityThread,如今一切準備就緒,它能夠真正執行Activity的啓動操做了。
複製代碼
相關文章:Android應用程序啓動過程源代碼分析面試
任務棧是一種後進先出的結構。位於棧頂的Activity處於焦點狀態,當按下back按鈕的時候,棧內的Activity會一個一個的出棧,而且調用其onDestory()方法。若是棧內沒有Activity,那麼系統就會回收這個棧,每一個APP默認只有一個棧,以APP的包名來命名. 一、standard:默認模式:每次啓動都會建立一個新的activity對象,放到目標任務棧中算法
二、singleTop:判斷當前的任務棧頂是否存在相同的activity對象,若是存在,則直接使用,若是不存在,那麼建立新的activity對象放入棧中bash
三、singleTask:在任務棧中會判斷是否存在相同的activity,若是存在,那麼會清除該activity之上的其餘activity對象顯示,若是不存在,則會建立一個新的activity放入棧頂網絡
四、singleIntance:會在一個新的任務棧中建立activity,而且該任務棧種只容許存在一個activity實例,其餘調用該activity的組件會直接使用該任務棧種的activity對象
方法一: 使用android:launchMode="standard|singleInstance|single Task|singleTop"來控制Acivity任務棧。
方法二: Intent Flags:
Intent intent=new Intent();
intent.setClass(MainActivity.this, MainActivity2.class);
intent.addFlags(Intent. FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
複製代碼
Flags有不少,好比:
Intent.FLAG_ACTIVITY_NEW_TASK 至關於singleTask
Intent. FLAG_ACTIVITY_CLEAR_TOP 至關於singleTop
相關文章:Android總結篇系列:Activity Intent Flags及Task相關屬性
Activity和Service以及Application的Context是不同的,Activity繼承自ContextThemeWraper.其餘的繼承自ContextWrapper.
每個Activity和Service以及Application的Context都是一個新的ContextImpl對象 getApplication()用來獲取Application實例的,可是這個方法只有在Activity和Service中才能調用的到。那麼也許在絕大多數狀況下咱們都是在Activity或者Service中使用Application的,可是若是在一些其它的場景,好比BroadcastReceiver中也想得到Application的實例,這時就能夠藉助getApplicationContext()方法.
getApplicationContext()比getApplication()方法的做用域會更廣一些,任何一個Context的實例,只要調用getApplicationContext()方法均可以拿到咱們的Application對象。
Context的數量等於Activity的個數 + Service的個數 + 1,這個1爲Application.
那Broadcast Receiver,Content Provider呢?Broadcast Receiver,Content Provider並非Context的子類,他們所持有的Context都是其餘地方傳過去的,因此並不計入Context總數。
1.在咱們取得Dialog對象後,需給它設置類型,即:
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT)
2.在Manifest中加上權限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
能夠
當訪問UI時,ViewRootImpl會調用checkThread
方法去檢查當前訪問UI的線程是哪一個,若是不是UI線程則會拋出異常 執行onCreate方法的那個時候ViewRootImpl還沒建立,沒法去檢查當前線程.ViewRootImpl的建立在onResume方法回調以後.
void checkThread() {
if (mThread != Thread.currentThread()) {
throw new CalledFromWrongThreadException(
"Only the original thread that created a view hierarchy can touch its views.");
}
}
複製代碼
非UI線程是能夠刷新UI的,前提是它要擁有本身的ViewRoot,即更新UI的線程和建立ViewRoot是同一個,或者在執行checkThread()
前更新UI.
相關文章:Android子線程真的不能更新UI麼
重寫ListView的onMeasure方法,來自定義高度:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
複製代碼
主要考察對MeasureSpec的三種模式的理解,相關文章.
爲了加速你的view,對於頻繁調用的方法,須要儘可能減小沒必要要的代碼。先從onDraw開始,須要特別注意不該該在這裏作內存分配的事情,由於它會致使GC,從而致使卡頓。在初始化或者動畫間隙期間作分配內存的動做。不要在動畫正在執行的時候作內存分配的事情。
你還須要儘量的減小onDraw被調用的次數,大多數時候致使onDraw都是由於調用了invalidate().所以請儘可能減小調用invaildate()的次數。若是可能的話,儘可能調用含有4個參數的invalidate()方法而不是沒有參數的invalidate()。沒有參數的invalidate會強制重繪整個view。
另一個很是耗時的操做是請求layout。任什麼時候候執行requestLayout(),會使得Android UI系統去遍歷整個View的層級來計算出每個view的大小。若是找到有衝突的值,它會須要從新計算好幾回。另外須要儘可能保持View的層級是扁平化的,這樣對提升效率頗有幫助。
若是你有一個複雜的UI,你應該考慮寫一個自定義的ViewGroup來執行他的layout操做。與內置的view不一樣,自定義的view可使得程序僅僅測量這一部分,這避免了遍歷整個view的層級結構來計算大小。這個PieChart 例子展現瞭如何繼承ViewGroup做爲自定義view的一部分。PieChart 有子views,可是它歷來不測量它們。而是根據他自身的layout法則,直接設置它們的大小。
1、相關概念的解釋
主線程(UI線程)
定義:當程序第一次啓動時,Android會同時啓動一條主線程(Main Thread) 做用:主線程主要負責處理與UI相關的事件
Message(消息)
定義:Handler接收和處理的消息對象(Bean對象)
做用:通訊時相關信息的存放和傳遞
ThreadLocal
定義:ThreadLocal是線程內部的存儲類,經過它能夠實如今每一個線程中存儲本身的私有數據。即數據存儲之後,只能在指定的線程中獲取這個存儲的對象,而其它線程則不能獲取到當前線程存儲的這個對象。
做用:負責存儲和獲取本線程的Looper
MessageQueue(消息隊列)
定義:採用單鏈表的數據結構來存儲消息列表
做用:用來存放經過Handler發過來的Message,按照先進先出執行
Handler(處理者)
定義:Message的主要處理者
做用:負責發送Message到消息隊列&處理Looper分派過來的Message
Looper(循環器)
定義:扮演Message Queue和Handler之間橋樑的角色
做用: 消息循環:循環取出Message Queue的Message 消息派發:將取出的Message交付給相應的Handler
二、本身畫下圖解
三、Handler發送消息有哪幾種方式?
1、sendMessage(Message msg) 2、post(Ruunable r)
四、Handler處理消息有哪幾種方式?
這個直接看dispatchMessage()
源碼:
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
//1. post()方法的處理方法
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
//2. sendMessage()方法的處理方法
handleMessage(msg);
}
}
//1. post()方法的最終處理方法
private static void handleCallback(Message message) {
message.callback.run();
}
//2. sendMessage()方法的最終處理方法
public void handleMessage(Message msg) {
}
複製代碼
5.Message、Handler、MessageQueue、Looper的之間的關係?
首先,是這個MessagQueue,MessageQueue是一個消息隊列,它能夠存儲Handler發送過來的消息,其內部提供了進隊和出隊的方法來管理這個消息隊列,其出隊和進隊的原理是採用單鏈表的數據結構進行插入和刪除的,即enqueueMessage()方法和next()方法。這裏提到的Message,其實就是一個Bean對象,裏面的屬性用來記錄Message的各類信息。
而後,是這個Looper,Looper是一個循環器,它能夠循環的取出MessageQueue中的Message,其內部提供了Looper的初始化和循環出去Message的方法,即prepare()方法和loop()方法。在prepare()方法中,Looper會關聯一個MessageQueue,並且將Looper存進一個ThreadLocal中,在loop()方法中,經過ThreadLocal取出Looper,使用MessageQueue的next()方法取出Message後,判斷Message是否爲空,若是是則Looper阻塞,若是不是,則經過dispatchMessage()方法分發該Message到Handler中,而Handler執行handlerMessage()方法,因爲handlerMessage()方法是個空方法,這也是爲何須要在Handler中重寫handlerMessage()方法的緣由。這裏要注意的是Looper只能在一個線程中只能存在一個。這裏提到的ThreadLocal,其實就是一個對象,用來在不一樣線程中存放對應線程的Looper。
最後,是這個Handler,Handler是Looper和MessageQueue的橋樑,Handler內部提供了發送Message的一系列方法,最終會經過MessageQueue的enqueueMessage()方法將Message存進MessageQueue中。咱們平時能夠直接在主線程中使用Handler,那是由於在應用程序啓動時,在入口的main方法中已經默認爲咱們建立好了Looper。
相關文章:blog.csdn.net/qq_30379689…
6.爲何在子線程中建立Handler會拋異常?
Handler的工做是依賴於Looper的,而Looper(與消息隊列)又是屬於某一個線程(ThreadLocal是線程內部的數據存儲類,經過它能夠在指定線程中存儲數據,其餘線程則沒法獲取到),其餘線程不能訪問。所以Handler就是間接跟線程是綁定在一塊兒了。所以要使用Handler必需要保證Handler所建立的線程中有Looper對象而且啓動循環。由於子線程中默認是沒有Looper的,因此會報錯。 正確的使用方法是:
private final class WorkThread extends Thread {
private Handler mHandler;
public Handler getHandler() {
return mHandler;
}
public void quit() {
mHandler.getLooper().quit();
}
@Override
public void run() {
super.run();
//建立該線程對應的Looper,
// 內部實現
// 1。new Looper()
// 2。將1步中的lopper 放在ThreadLocal裏,ThreadLocal是保存數據的,主要應用場景是:線程間數據互不影響的狀況
// 3。在1步中的Looper的構造函數中new MessageQueue();
//其實就是建立了該線程對用的Looper,Looper裏建立MessageQueue來實現消息機制
//對消息機制不懂得同窗能夠查閱資料,網上不少也講的很不錯。
Looper.prepare();
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.d("WorkThread", (Looper.getMainLooper() == Looper.myLooper()) + "," + msg.what);
}
};
//開啓消息的死循環處理即:dispatchMessage
Looper.loop();
//注意這3個的順序不能顛倒
Log.d("WorkThread", "end");
}
}
複製代碼
一、HandlerThread做用
當系統有多個耗時任務須要執行時,每一個任務都會開啓一個新線程去執行耗時任務,這樣會致使系統屢次建立和銷燬線程,從而影響性能。爲了解決這一問題,Google提供了HandlerThread,HandlerThread是在線程中建立一個Looper循環器,讓Looper輪詢消息隊列,當有耗時任務進入隊列時,則不須要開啓新線程,在原有的線程中執行耗時任務便可,不然線程阻塞。
二、HanlderThread的優缺點
handleMessage()
方法中執行異步任務。HandlerThread.start()
方法,Thread會先調用run方法,建立Looper對象。相關文章:Android 多線程之IntentService 徹底詳解
它本質是一種特殊的Service,繼承自Service而且自己就是一個抽象類
它能夠用於在後臺執行耗時的異步任務,當任務完成後會自動中止
它擁有較高的優先級,不易被系統殺死(繼承自Service的緣故),所以比較適合執行一些高優先級的異步任務 它內部經過HandlerThread和Handler實現異步操做
建立IntentService時,只需實現onHandleIntent和構造方法,onHandleIntent爲異步方法,能夠執行耗時操做
即便咱們屢次啓動IntentService,但IntentService的實例只有一個,這跟傳統的Service是同樣的,最終IntentService會去調用onHandleIntent執行異步任務。
當任務完成後,IntentService會自動中止,而不須要手動調用stopSelf()
。另外,能夠屢次啓動IntentService,每一個耗時操做都會以工做隊列的方式在IntentService
中onHandlerIntent()
回調方法中執行,而且每次只會執行一個工做線程。
相關文章:Android 多線程之IntentService 徹底詳解
一、AsyncTask是什麼
AsyncTask是一種輕量級的異步任務類,它能夠在線程池中執行後臺任務,而後把執行的進度和最終結果傳遞給主線程並主線程中更新UI,經過AsyncTask能夠更加方便執行後臺任務以及在主線程中訪問UI,可是AsyncTask並不適合進行特別耗時的後臺任務,對於特別耗時的任務來講,建議使用線程池。
二、AsyncTask使用方法
三個參數 Params:表示後臺任務執行時的參數類型,該參數會傳給AysncTask的doInBackground()方法 Progress:表示後臺任務的執行進度的參數類型,該參數會做爲onProgressUpdate()方法的參數 Result:表示後臺任務的返回結果的參數類型,該參數會做爲onPostExecute()方法的參數 五個方法 onPreExecute():異步任務開啓以前回調,在主線程中執行 doInBackground():執行異步任務,在線程池中執行 onProgressUpdate():當doInBackground中調用publishProgress時回調,在主線程中執行 onPostExecute():在異步任務執行以後回調,在主線程中執行 onCancelled():在異步任務被取消時回調
三、AsyncTask引發的內存泄漏
緣由:非靜態內部類持有外部類的匿名引用,致使Activity沒法釋放 解決: AsyncTask內部持有外部Activity的弱引用 AsyncTask改成靜態內部類 Activity的onDestory()中調用AsyncTask.cancel()
4.結果丟失
屏幕旋轉或Activity在後臺被系統殺掉等狀況會致使Activity的從新建立,以前運行的AsyncTask會持有一個以前Activity的引用,這個引用已經無效,這時調用onPostExecute()再去更新界面將再也不生效。
五、AsyncTask並行or串行
AsyncTask在Android 2.3以前默認採用並行執行任務,AsyncTask在Android 2.3以後默認採用串行執行任務 若是須要在Android 2.3以後採用並行執行任務,能夠調用AsyncTask的executeOnExecutor();
6.AsyncTask內部的線程池
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
sDefaultExecutor
是SerialExecutor
的一個實例,並且它是個靜態變量。也就是說,一個進程裏面全部AsyncTask對象都共享同一個SerialExecutor
對象。
相關文章:android多線程-AsyncTask之工做原理深刻解析
通常狀況下第一輪都是基礎面試,須要紮實的基礎
最經常使用的Android 基礎知識
Java 基礎知識
瞭解一些 經常使用東西的原理,例如:handler, thread 等
項目中的技術點
第二輪的時候須要瞭解更深層次的東西
Android 事件分發機制原理
Android 繪圖機制原理
WindowManager 的相關知識
進程間傳輸方式
Java 內存管理機制
一些經常使用的 list,map 原理,以及子類之間的差異
能進入第三輪基本沒什麼問題,可是要注意如下問題
該輪通常是 老大或者部門負責人,問的問題通常都看 深度與廣度 當問及薪水的時候,要說一個合適的,小公司隨意,大公司必定要慎重,小心裏沒底的時候,能夠告訴對方,讓對方給一個合理的薪資。通常都是在原工資基礎之上增加,聽獵頭說通常漲幅都在15%-30%,超 NB 的能夠要30%及以上,若是感受本身還不錯的,挺厲害的,建議最高20%,通常人就定在15% 左右最靠譜。公司內部通常有一套機制,根據公司狀況而定。
咱們的面試原則就是拿到合理薪資,獲得 offer
我的發展狀況,這個問題很難回答,若是和公司方向不符合,極有可能和公司無緣。建議多試探性的問問公司缺乏什麼,你可否給予公司對應的東西。固然對於有自我追求的人,那能夠放心大膽的提。個人方向就是架構師,哈哈哈,挺極端的,別學我哦。我感受選擇都是雙向的,所以我知道本身須要的是什麼。
你最擅長什麼UI 仍是其餘什麼?這個問題更很差回答。你要說你擅長 UI,是否是意味着你其餘能力就不行?雖然我不知道面試官的用意,可是我能感受到,這個問題不是那麼好回答,我會回答說本身都行,來什麼業務接什麼需求。可能回答不太好,總之和公司的職位吻合就行,這樣總不至於出錯吧。
摘自文章:一個五年Android開發者百度、阿里、聚美、映客的面試心經
www.jackywang.tech/AndroidInte…
github.com/AweiLoveAnd…
github.com/hadyang/int…
jingbin.me/2017/02/20/…
github.com/Freelander/…
www.jianshu.com/p/1d3a2227f…
github.com/stormzhang/…
www.zhihu.com/question/37…
Android 2018 最新面試題(3-5年經驗我的面試經歷)