隨着互聯網的迅速發展,Android技術也是發生很大的變化,要求也是越來高了,在11,12年只要會基本的Android組件,會listview,分享就感受很牛了,智能手機的發展,及用戶普通追求高效率,用戶體驗的提高,要求開發人員必須會懂實現原理及優化APP程序;不論是面試他人仍是被面試目前都常常問到原理性的問題,handler實現原理,activity啓動原理,進程通訊原理,多線程等等,接下來我聊聊面試中常常遇到的原理問題;java
一,ContentProvider進程間如何共享數據的,數據存在哪裏?面試
1,一個程序能夠經過實現一個ContentProvider的抽象接口將本身的數據徹底暴露出去,並且ContentProvider是以相似數據庫中表的方式將數據暴露的。那麼外界獲取其提供的數據,也就應該與從數據庫中獲取數據的操做基本同樣,只不過是採用URL來表示外界須要訪問的「數據庫」。數據庫
2,ContentProvider提供了一種多應用間數據共享的方式。ContentProvider是個實現了一組用於提供其餘應用程序存取數據的標準方法的類。應用程序能夠在ContentProvider中執行以下操做:查詢數據、修改數據、添加數據、刪除數據。多線程
3,標準的ContentProvider:Android提供了一些已經在系統中實現的標準,好比聯繫人信息,圖片庫等等,能夠用這些ContentProvider來訪問設備上存儲的聯繫人信息、圖片等等。app
4,在ContentProvider中使用的查詢字符串有別於標準的SQL查詢,不少諸如select、add、delete、modify等操做都使用一種特殊的URL進行,這種URL由3部分組成,「content://」,表明數據的路徑和一個可選的表示數據的ID。ide
content://media/internal/images 這個URL將返回設備上存儲的全部圖片oop
content://contacts/people/ 這個URL將返回設備上的全部聯繫人信息優化
content://contacts/people/9 這個URL返回單個結果(聯繫人信息中ID爲9的聯繫人記錄)線程
5,若是想要存儲字節型數據,好比位圖文件等,那保存該數據的數據列實際上是一個表示實際保存保存文件的URL字符串,客戶端經過它來讀取對應的文件數據,處理這種數據類型的ContentProvider須要實現一個名爲_data的字段,_data字段列出了該文件在Android文件系統上的精確路徑。這個字段不只是供客戶端使用,並且也能夠供ContentResolver使用。客戶端能夠調用ContentResolver.openOutputStream()方法來處理該URL指向的文件資源,若是是ContentResolver自己的話,因爲其持有的權限比客戶端要高,因此它能直接訪問該數據文件。code
ContentProvider使用Android文件系統或者SQLite數據庫來保持數據,可是也能夠以任何方式來存儲。本例用SQLite數據庫來保持數據。
二,Android中的handler你們都熟悉,handler是原理及looper.loop在主線程輪詢爲何不會致使主線程阻塞?
一、handler封裝消息的發送(主要包括消息發送給誰)
二、Looper——消息封裝的載體。(1)內部包含一個MessageQueue,全部的Handler發送的消息都走向這個消息隊列;(2)Looper.Looper方法,就是一個死循環,不斷地從MessageQueue取消息,若是有消息就處理消息,沒有消息就阻塞。
三、MessageQueue,一個消息隊列,添加消息,處理消息
四、handler內部與Looper關聯,handler->Looper->MessageQueue,handler發送消息就是向MessageQueue隊列發送消息。
activityThread並非一個Thread,只是一個final類,主線通常是從這個類的main方法開始,在activityThread中能夠看到有Looper,接着能夠找找對應的handler,繼承了handler 在handleMessage的部分看出 Activity 的生命週期都有對應的 case 條件了
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
case RELAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
handleRelaunchActivity(r);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
case PAUSE_ACTIVITY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2,
(msg.arg1&2) != 0);
maybeSnapshot();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case PAUSE_ACTIVITY_FINISHING:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
handlePauseActivity((IBinder)msg.obj, true, (msg.arg1&1) != 0, msg.arg2,
(msg.arg1&1) != 0);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case STOP_ACTIVITY_SHOW:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop");
handleStopActivity((IBinder)msg.obj, true, msg.arg2);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case STOP_ACTIVITY_HIDE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop");
handleStopActivity((IBinder)msg.obj, false, msg.arg2);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case SHOW_WINDOW:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityShowWindow");
handleWindowVisibility((IBinder)msg.obj, true);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case HIDE_WINDOW:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityHideWindow");
handleWindowVisibility((IBinder)msg.obj, false);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case RESUME_ACTIVITY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
handleResumeActivity((IBinder) msg.obj, true, msg.arg1 != 0, true);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
ActivityThread 有個 getHandler 方法,獲得這個 handler 就能夠發送消息,而後 loop 裏就分發消息,而後就發給 handler, 而後就執行到 H(Handler )裏的對應代碼。因此這些代碼就不會卡死~,有消息過來就能執行。
一切從main()方法開始
Android中,一個應用程序的開始能夠說就是從ActivityThread.java中的main()方法開始的。都是學過Java的人,想必也都知道Java的程序入口就是main()方法。從這點而言,咱們能夠把它想成是一個Java程序(注意,不是說Android是個Java程序哦)去理解。
main()方法中主要作的事情有:
初始化主線程的Looper、主Handler。並使主線程進入等待接收Message消息的無限
public static void main(String[] args){
...
Looper.prepareMainLooper();
//初始化Looper
...
ActivityThread thread = new ActivityThread();
//實例化一個ActivityThread
thread.attach(false);
//這個方法最後就是爲了發送出建立Application的消息
...
Looper.loop();
//主線程進入無限循環狀態,等待接收消息
}