Android開發必不可少原理問題

隨着互聯網的迅速發展,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 )裏的對應代碼。因此這些代碼就不會卡死~,有消息過來就能執行。

 

 

3、Activity啓動過程

一切從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();

//主線程進入無限循環狀態,等待接收消息

 

}

獲取更多內容關注公衆號:

相關文章
相關標籤/搜索