2017 Android 面試題
2017 Android 面試題 [ 基礎與細節 ]
感謝@chuyao
我自己整理了些答案,不對或者不妥的地方請大家指出,謝謝。
1. Activity建立在哪些窗口組件之上?順帶涉及View的事件傳遞問題。
沒讀懂問題,=。=不知道是不是問Activity的UI結構,如果是可以參考這篇文章。
對於View的事件傳遞,則可以從 Activity --> ViewGroup --> ...... --> Activity
的** U型 **消費結構去說。
2. 什麼情況下,Activity的onNewInstent方法會執行?Activity的啟動模式相關。
當此Activity的實例已經存在,並且此時的啟動模式為SingleTask
和SingleInstance
,另外當這個實例位於棧頂且啟動模式為SingleTop
時也會觸發onNewInstent
。
3. Activity A使用startForResult啟動Activity B,B什麼都不做並返回A,A中的onActivityResult回調是否會執行?
startActivity方法,最終都是調用startActivityForResult
方法。默認的requestCode = -1 resultCode = RESULT_CANCELED = 0
,當你的requestCode != -1
時,onActivityResult
一定會被調用。
4. Fragment能否不依賴於Activity存在?簡析一下Fragment的棧管理。
Fragment不能獨立存在,它必須嵌入到activity中,而且Fragment的生命週期直接受所在的activity的影響。
// Create new fragment and transaction
Fragment newFragment = new ExampleFragment;
FragmentTransaction transaction = getFragmentManager.beginTransaction;
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit;
transaction只是記錄了從一個狀態到另一個狀態的變化過程,即比如從FragmentA替換到FragmentB的過程,當通過函數transaction.addToBackStack(null)將這個事務添加到回退棧,則會記錄這個事務的狀態變化過程,如從FragmentA —>FragmentB,當用戶點擊手機回退鍵時,因為transaction的狀態變化過程被保存,則可以將事務的狀態變化過程還原,即將FragmentB —> FragmentA.
添加到回退棧的函數:transaction.addToBackStack(null);
5. 能否將一個Activity放到系統的最近任務列表裡,獨立於宿主app任務卡之外?
我印象中是可以做到了,平時沒用到,知道的同學請@我,謝謝!
6. 對於同一個Service,在被start啟動之後還能不能被bind?
能
服務基本上分為兩種形式:
啟動
當應用組件(如 Activity)通過調用 startService 啟動服務時,服務即處於“啟動”狀態。一旦啟動,服務即可在後臺無限期運行,即使啟動服務的組件已被銷燬也不受影響。 已啟動的服務通常是執行單一操作,而且不會將結果返回給調用方。例如,它可能通過網絡下載或上傳文件。 操作完成後,服務會自行停止運行。
綁定
當應用組件通過調用 bindService 綁定到服務時,服務即處於“綁定”狀態。綁定服務提供了一個客戶端-服務器接口,允許組件與服務進行交互、發送請求、獲取結果,甚至是利用進程間通信 (IPC) 跨進程執行這些操作。 僅當與另一個應用組件綁定時,綁定服務才會運行。 多個組件可以同時綁定到該服務,但全部取消綁定後,該服務即會被銷燬。
雖然本文檔是分開概括討論這兩種服務,但是您的服務可以同時以這兩種方式運行,也就是說,它既可以是啟動服務(以無限期運行),也允許綁定。問題只是在於您是否實現了一組回調方法:onStartCommand(允許組件啟動服務)和 onBind(允許綁定服務)。
來自官方文檔
7. Service有哪些派生類?這些派生類的使用場景是什麼?
這個問題不知道問的具體是什麼,如果是要 IntentService
那麼可以參考官方文檔的解釋與使用說明:
擴展 IntentService 類
由於大多數啟動服務都不必同時處理多個請求(實際上,這種多線程情況可能很危險),因此使用 IntentService 類實現服務也許是最好的選擇。
IntentService 執行以下操作:
創建默認的工作線程,用於在應用的主線程外執行傳遞給 onStartCommand 的所有 Intent。
創建工作隊列,用於將 Intent 逐一傳遞給 onHandleIntent 實現,這樣您就永遠不必擔心多線程問題。
在處理完所有啟動請求後停止服務,因此您永遠不必調用 stopSelf。
提供 onBind 的默認實現(返回 null)。
提供 onStartCommand 的默認實現,可將 Intent 依次發送到工作隊列和 onHandleIntent 實現。
綜上所述,您只需實現 onHandleIntent 來完成客戶端提供的工作即可。(不過,您還需要為服務提供小型構造函數。)
以下是 IntentService 的實現示例:
public class HelloIntentService extends IntentService {
/**
* A constructor is required, and must call the super IntentService(String)
* constructor with a name for the worker thread.
*/
public HelloIntentService {
super("HelloIntentService");
}
/**
* The IntentService calls this method from the default worker thread with
* the intent that started the service. When this method returns, IntentService
* stops the service, as appropriate.
*/
@Override
protected void onHandleIntent(Intent intent) {
// Normally we would do some work here, like download a file.
// For our sample, we just sleep for 5 seconds.
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// Restore interrupt status.
Thread.currentThread.interrupt;
}
}
}
您只需要一個構造函數和一個 onHandleIntent 實現即可。
如果您決定還重寫其他回調方法(如 onCreate()、onStartCommand() 或 onDestroy()),請確保調用超類實現,以便 IntentService 能夠妥善處理工作線程的生命週期。
例如,onStartCommand 必須返回默認實現(即,如何將 Intent 傳遞給 onHandleIntent()):
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show;
return super.onStartCommand(intent,flags,startId);
}
除 onHandleIntent 之外,您無需從中調用超類的唯一方法就是 onBind(僅當服務允許綁定時,才需要實現該方法)。
8. Service與其它組件之間的通信實現方式有哪些?
- binder
- broadcast
- 其他參見線程和進程的通信方式
9. View的post(Runnable r)方法裡,r會帶來一個新的線程嗎?多線程相關。
不會,最終還是handler
發送消息,執行在UI
線程。
如下是源碼和註釋:
/**
* <p>Causes the Runnable to be added to the message queue.
* The runnable will be run on the user interface thread.</p>
*
* @param action The Runnable that will be executed.
*
* @return Returns true if the Runnable was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
*
* @see #postDelayed
* @see #removeCallbacks
*/
public boolean post(Runnable action) {
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
return attachInfo.mHandler.post(action);
}
// Postpone the runnable until we know on which thread it needs to run.
// Assume that the runnable will be successfully placed after attach.
getRunQueue.post(action);
return true;
}
10. 在非UI線程中使用Handler需要注意哪些問題?
new Thread{
public void run{
Looper.prepare;//給當前線程初始化Looper
Toast.makeText(getApplicationContext,"更新UI",0).show;//Toast初始化的時候會new Handler;無參構造默認獲取當前線程的Looper,如果沒有prepare過,則拋出題主描述的異常。上一句代碼初始化過了,就不會出錯。
Looper.loop;//這句執行,Toast排隊show所依賴的Handler發出的消息就有人處理了,Toast就可以吐出來了。但是,這個Thread也阻塞這裡了,因為loop是個for (;;) ...
}
}.start;
參考:
11. 自定義View時有哪些重要的方法,它們的作用及執行順序是怎樣的?
按照順序:onMeasure
-->onLayout
-->onDraw
.其他的自己擴展吧。
12. 如何單獨對ListView上的一個item進行更新?
- 更新對應view的內容
- 通過ViewHolder去設置值
- 調用一次getView方法(Google IO 推薦)
13. 簡析一下大圖片的加載處理。
對Bitmap的理解,然後就是壓縮圖片。
14. 設計師只給了一套1280*800的UI圖標註,如何進行其它分辨率尺寸屏幕的適配?
名稱 | 像素密度範圍 | 圖片大小 |
---|---|---|
mdpi | 120dp~160dp | 48×48px |
hdpi | 160dp~240dp | 72×72px |
xhdpi | 240dp~320dp | 96×96px |
xxhdpi | 320dp~480dp | 144×144px |
xxxhdpi | 480dp~640dp | 192×192px |
以 720*1080 5英寸為例:
(720^2 + 1080^2)開方=260
放在xhdpi中。
本題中同理可以算得 293,還是xhdpi中。
15. 6.0系統新權限機制的解決方案。
這個。。。沒什麼好說的,真正瞭解的很好說,不瞭解的話就有點繞。
? 你們精通的開源框架,問題來了
寫各種精通其實是可以的,要麼真牛x,如果不是很牛x那就在最後加上一條精通----精通各種被打臉。
16. EventBus的機制是什麼?和Handler的區別怎樣?
EventBus
是採用觀察者模式實現的事件訂閱總線,可以用在應用程序中,組件之間,線程之間的通信,並且由於事件可以是任意類型的對象,所以使用起來更加的方便快捷。
Handler
是 Android 的消息機制,集中解決線程間通信問題。
17. RxJava的機制是什麼?
RxJava是使用Java語言,以響應式編程思維來進行編程的Java類庫。參考ReactiveX
。
18. Butterknife的機制是什麼?
Java Annotation Processing技術,在Java代碼編譯成Java字節碼的時候就已經處理了@Bind、@OnClick(ButterKnife還支持很多其他的註解)這些註解了。
Annotation processing 是javac中用於編譯時掃描和解析Java註解的工具
Annotation processing是在編譯階段執行的,它的原理就是讀入Java源代碼,解析註解,然後生成新的Java代碼。新生成的Java代碼最後被編譯成Java字節碼,註解解析器(Annotation Processor)不能改變讀入的Java 類,比如不能加入或刪除Java方法。
參考:ButterKnife框架原理
19. Okhttp是基於HTTP連接還是Socket連接?
基於Http
的。
20. 例舉一種ORM框架,說說它的優缺點。
我熟悉的兩種GreenDao3
和AndroidActive
,GreenDao 比較常規,註解不多(我這裡都是指3.0版本後,之前的版本在生存實體的時候略顯麻煩。),AndroidActive 相對而言註解較多,最後的綜合性能上 GreenDao 排第一毫無爭議。硬要說缺點的話就是 GreenDao 體積稍大。