android面試題-簡答題(一)

來源:互聯網
上載者:User

1、在多線程編程這塊,我們經常要使用Handler,Thread和Runnable這三個類,那麼他們之間的關係你是否弄清楚了呢?

答:Android的CPU分配的最小單元是線程,Handler一般是在某個線程裡建立的,因而Handler和Thread就是相互綁定的,一一對應。而Runnable是一個介面,Thread是Runnable的子類。所以說,他倆都算一個進程。HandlerThread顧名思義就是可以處理訊息迴圈的線程,他是一個擁有Looper的線程,可以處理訊息迴圈。與其說Handler和一個線程綁定,不如說Handler是和Looper一一對應的。最後需要說明的是,在UI線程(主線程)中: mHandler=new Handler(); 

mHandler.post(new Runnable(){

  void run(){

  //執行代碼...}

  });

  這個線程其實是在UI線程之內啟動並執行,並沒有建立線程。

  常見的建立線程的方法是:

  Thread thread = new Thread();

  thread.start();

  HandlerThread thread = newHandlerThread("string");

  thread.start();

2、如何設定應用程式為系統層級的應用?

答:apk 擷取system許可權;如何擷取如下:解釋串連:http://blog.csdn.net/superkris/article/details/7709504

第一個方法簡單點,不過需要在Android系統源碼的環境下用make來編譯:

1.在應用程式的AndroidManifest.xml中的manifest節點中加入android:sharedUserId="android.uid.system"這個屬性。

2.修改Android.mk檔案,加入LOCAL_CERTIFICATE := platform這一行

3.使用mm命令來編譯,產生的apk就有修改系統時間的許可權了。

第二個方法是直接把eclipse編出來的apk用系統的簽名檔案簽名

1.加入android:sharedUserId="android.uid.system"這個屬性。

2.使用eclipse編譯出apk檔案。

3.使用目標系統的platform密鑰來重新給apk檔案簽名。首先找到密鑰檔案,在我ndroid源碼目錄中的位置是"build/target/product/security",下面的platform.pk8和platform.x509.pem兩個檔案。然後用Android提供的Signapk工具來簽名,signapk的原始碼是在"build/tools/signapk"下,編譯後在out/host/linux-x86/framework下,用法為java -jarsignapk.jar platform.x509.pem platform.pk8 input.apk output.apk"。

加入android:sharedUserId="android.uid.system"這個屬性。通過Shared User id,擁有同一個User id的多個APK可以配置成運行在同一個進程中。那麼把程式的UID配成android.uid.system,也就是要讓程式運行在系統進程中,這樣就有許可權來修改系統時間了。

只是加入UID還不夠,如果這時候安裝APK的話發現無法安裝,提示簽名不符,原因是程式想要運行在系統進程中還要有目標系統的platform key,就是上面第二個方法提到的platform.pk8和platform.x509.pem兩個檔案。用這兩個key簽名後apk才真正可以放入系統進程中。第一個方法中加入LOCAL_CERTIFICATE :=platform其實就是用這兩個key來簽名。

這也有一個問題,就是這樣產生的程式只有在原始的Android系統或者是自己編譯的系統中才可以用,因為這樣的系統才可以拿到platform.pk8和platform.x509.pem兩個檔案。要是別家公司做的Android上連安裝都安裝不了。試試原始的Android中的key來簽名,程式在模擬器上運行OK,不過放到G3上安裝直接提示"Package... has no signatures that match those in shared user android.uid.system",這樣也是保護了系統的安全。

3、談談Android的IPC(處理序間通訊)機制

答:http://blog.csdn.net/luoshengyang/article/details/6618363

Android系統中,每一個應用程式都是由一些Activity和Service組成的,這些Activity和Service有可能運行在同一個進程中,也有可能運行在不同的進程中,android的IPC機制也就是Binder機制,Android系統是基於Linux核心的,而Linux核心繼承和相容了豐富的Unix系統處理序間通訊(IPC)機制, 但是,Android系統沒有採用上述提到的各種處理序間通訊機制,而是採用Binder機制,Binder是一種處理序間通訊機制,它是一種類似於COM和CORBA分布式組件架構,通俗一點,其實是提供遠端程序呼叫(RPC)功能。從英文字面上意思看,Binder具有粘結劑的意思,那麼它把什麼東西粘結在一起呢?在Android系統的Binder機制中,由一系統組件組成,分別是Client、Server、Service Manager和Binder驅動程式,其中Client、Server和Service Manager運行在使用者空間,Binder驅動程式運行核心空間。Binder就是一種把這四個組件粘合在一起的粘結劑了,其中,核心組件便是Binder驅動程式了,Service Manager提供了輔助管理的功能,Client和Server正是在Binder驅動和ServiceManager提供的基礎設施上,進行Client-Server之間的通訊;

1. Client、Server和Service Manager實現在使用者空間中,Binder驅動程式實現在核心空間中

2. Binder驅動程式和Service Manager在Android平台中已經實現,開發人員只需要在使用者空間實現自己的Client和Server

3.Binder驅動程式提供裝置檔案/dev/binder與使用者空間互動,Client、Server和Service Manager通過open和ioctl檔案操作函數與Binder驅動程式進行通訊

4. Client和Server之間的處理序間通訊通過Binder驅動程式間接實現

5. Service Manager是一個守護進程,用來管理Server,並向Client提供查詢Server介面的能力

4、apk安裝卸載的原理

答:http://blog.csdn.net/lizhiguo0532/article/details/7077432

http://www.itivy.com/android/archive/2011/8/10/android-apk-setup-method-and-principles.html

APK安裝可以通過以下四種方式:
1. 系統應用安裝,開機時完成系統應用的檢查,沒安裝就安裝,安裝就跳過,無安裝介面。
2. 網路下載應用安裝,通過market應用完成,無安裝介面。
3. ADB工具安裝,無安裝介面
4. 通過SD卡來安裝apk,有安裝介面,由packageinstaller.apk應用處理安裝及卸載過程的介面。

應用安裝涉及到如下幾個目錄:
system/app 系統內建的應用程式,無法刪除
data/app 使用者程式安裝的目錄,有刪除許可權
data/data 存放應用程式的資料
Data/dalvik-cache 將apk中的dex檔案安裝到dalvik-cache目錄下
(dex檔案是dalvik虛擬機器的可執行檔,其大小約為原始apk檔案大小的四分之一)

安裝過程:複製APK安裝包到data/app目錄下,解壓並掃描安裝包,把dex檔案(Dalvik位元組碼)儲存到dalvik-cache目錄,並data/data目錄下建立對應的應用資料目錄。

卸載過程:刪除安裝過程中在上述三個目錄下建立的檔案及目錄。

5、如何做適配1)android有H、L、M、X、XX四個不同的檔案夾存放不同解析度的圖片,系統會自動載入

2)位移量d的設定可以在values-hpdi,values-mdpi,values-ldpi三種檔案夾中的dimens.xml檔案進行設定

值得一提的是:

40dp

-14dp

這裡的負數是完全起作用的,系統會認為它是一個負值

3)各大手機廠商對於Android作業系統都有或多或少的改動,當然這些改動會對我們應用程式產生某些影響

比如:

(1)系統原始碼中串連music服務的aidl檔案所在包名:com.android.music

(2)LG則可能將該aidl檔案修改所在的包(例如修改為 com.android.music.player),並且修改其中的檔案內容(增加一個方法,或者減少幾個方法,或者修改方法名稱)那麼我們的應用要想在LG的手機上發布,那麼我們就必須改變所要串連的aidl檔案,必須跟LG廠商修改的完全一致。

6、是否進行過apk反編譯,如何防止反編譯反編譯:

Android反編譯工具

· dex2jar + jdgui

· apktool

防止反編譯:

· 代碼加密

這方式,也只能想想,一旦你自己加密了,Android系統都不認識你了,還怎麼運行?(如果有那估計就是eoe現在推的愛加密吧).

· 代碼混淆

這種方式,其實我不大願意將他歸類於防止反編譯,從Android、Java編譯原理上來說,針對自身代碼做混淆等操作,必然防止不了反編譯這個事實。他能做到的就是將字元,函數等混淆成各種a,b,c,d,1,2,3等。

這種方式一般稱為,
妨礙對反編譯代碼的閱讀、觀看和理解

Android中主要是針對 proguard.cfg 的配置來實現。

具體的實現網上針對這部分的解釋已經太多,所以這裡不詳細介紹了。

· 動態載入類

這種方式的啟發是根據web端來的。Web端你要防止,那就不發布唄。

所以我們可以將我們重要的源碼,丟在伺服器上,必要的時候通過DexClassLoader類去載入重要類。來防止核心代碼被反編譯。

具體可看DexClassLoader樣本

· 用NDK開發核心代碼

從上面已經能知道,C/C++等編譯型語言的反組譯碼難度。所以我們可以放心的使用NDK去開發,產生SO庫檔案再來調用。

PS:部分資源檔若十分珍貴,可以通過 #include直接編譯到庫裡(當然記憶體可能就大了),這種方式可以自己考慮。

7、Android的動畫分類以及兩種動畫的闡述

Tween動畫

又稱“補間動畫”、“中間動畫”,最早接觸Tween類是在學習Flash時候,使用ActionScript做動畫的時候,使用過類Tween。

Tween動畫主要的功能是在繪製動畫前設定動畫繪製的軌跡,包括時間, 位置 ,等等。但是Tween動畫的缺點是它只能設定起始點與結束點的兩幀,中間過程全部由系統幫我們完成。所以在幀數比較多的遊戲開發中是不太會用到它的。
Tween一共提供了4中動畫的效果

Scale:縮放動畫
Rotate:旋轉動畫
Translate:移動動畫
Alpha::透明漸層動畫

Frame動畫

又稱幀動畫,主要顯示方式是為動畫的總標籤,這裡面放著幀動畫標籤,也就是說若干標籤的幀 組合在一起就是幀動畫了。 標籤中android:oneshot="false"這是一個非常重要的屬性,預設為false 表示 動畫迴圈播放, 如果這裡寫true 則表示動畫只播發一次。 標籤中記錄著每一幀的資訊android:drawable="@drawable/a"表示這一幀用的圖片為"a",下面以此類推。 android:duration="100" 表示這一幀持續100毫秒,可以根據這個值來調節動畫播放的速度。

8、AIDL全稱,如何工作,可處理那些資料答:AIDL的英文全稱是Android Interface Define Language
當A進程要去調用B進程中的service時,並實現通訊,我們通常都是通過AIDL來操作的
A工程:
首先我們在net.blogjava.mobile.aidlservice包中建立一個RemoteService.aidl檔案,在裡面我們自訂一個介面,含有方法get。ADT外掛程式會在gen目錄下自動產生一個RemoteService.java檔案,該類中含有一個名為RemoteService.stub的內部類,該內部類中含有aidl檔案介面的get方法。
說明一:aidl檔案的位置不固定,可以任意
然後定義自己的MyService類,在MyService類中自訂一個內部類去繼承RemoteService.stub這個內部類,實現get方法。在onBind方法中返回這個內部類的對象,系統會自動將這個對象封裝成IBinder對象,傳遞給他的調用者。
其次需要在AndroidManifest.xml檔案中配置MyService類,代碼如下:







為什麼要指定調用AIDL服務的ID,就是要告訴外界MyService這個類能夠被別的進程訪問,只要別的進程知道這個ID,正是有了這個ID,B工程才能找到A工程實現通訊。
說明:AIDL並不需要許可權
B工程:
首先我們要將A工程中產生的RemoteService.java檔案拷貝到B工程中,在bindService方法中綁定aidl服務
綁定AIDL服務就是將RemoteService的ID作為intent的action參數。
說明:如果我們單獨將RemoteService.aidl檔案放在一個包裡,那個在我們將gen目錄下的該包拷貝到B工程中。如果我們將RemoteService.aidl檔案和我們的其他類存放在一起,那麼我們在B工程中就要建立相應的包,以保證RmoteService.java檔案的報名正確,我們不能修改RemoteService.java檔案
bindService(newInten("net.blogjava.mobile.aidlservice.RemoteService"),serviceConnection,Context.BIND_AUTO_CREATE);
ServiceConnection的onServiceConnected(ComponentName name, IBinderservice)方法中的service參數就是A工程中MyService類中繼承了RemoteService.stub類的內部類的對象。9、Android系統中GC什麼情況下不會出現記憶體泄露

1.資料庫的cursor沒有關閉

2.構造adapter時,沒有使用緩衝contentview
衍生listview的最佳化問題-----減少建立view的對象,充分使用contentview,可以使用一靜態類來最佳化處理getview的過程/

3.Bitmap對象不使用時採用recycle()釋放記憶體

4.activity中的對象的生命週期大於activity
調試方法: DDMS==> HEAPSZIE==>dataobject==>[TotalSize]

10、什麼情況會導致Force Close ?如何避免?能否捕獲導致其的異常?
答:一般像null 指標啊,可以看起logcat,然後對應到程式中 來解決錯誤11、activity的4種模式,以及不同模式的作用。http://blog.csdn.net/zhangjg_blog/article/details/10923643

activity有四種啟動模式,分別為standard,singleTop,singleTask,singleInstance。如果要使用這四種啟動模式,必須在manifest檔案中標籤中的launchMode屬性中配置,如:

android:label="@string/interstitial_label"
android:theme="@style/Theme.Dialog"
android:launchMode="singleTask"
standard

標準啟動模式,也是activity的預設啟動模式。在這種模式下啟動的activity可以被多次執行個體化,即在同一個任務中可以存在多個activity的執行個體,每個執行個體都會處理一個Intent對象。如果Activity A的啟動模式為standard,並且A已經啟動,在A中再次啟動Activity A,即調用startActivity(new Intent(this,A.class)),會在A的上面再次啟動一個A的執行個體,即當前的桟中的狀態為A-->A。

singleTop

如果一個以singleTop模式啟動的activity的執行個體已經存在於任務桟的桟頂,那麼再啟動這個Activity時,不會建立新的執行個體,而是重用位於棧頂的那個執行個體,並且會調用該執行個體的onNewIntent()方法將Intent對象傳遞到這個執行個體中。舉例來說,如果A的啟動模式為singleTop,並且A的一個執行個體已經存在於棧頂中,那麼再調用startActivity(new Intent(this,A.class))啟動A時,不會再次建立A的執行個體,而是重用原來的執行個體,並且調用原來執行個體的onNewIntent()方法。這是任務桟中還是這有一個A的執行個體。

如果以singleTop模式啟動的activity的一個執行個體已經存在與任務桟中,但是不在桟頂,那麼它的行為和standard模式相同,也會建立多個執行個體。

singleTask

Google的官方文檔上稱,如果一個activity的啟動模式為singleTask,那麼系統總會在一個新任務的最底部(root)啟動這個activity,並且被這個activity啟動的其他activity會和該activity同時存在於這個新任務中。如果系統中已經存在這樣的一個activity則會重用這個執行個體,並且調用他的onNewIntent()方法。即,這樣的一個activity在系統中只會存在一個執行個體。

其實官方文檔中的這種說法並不準確,啟動模式為singleTask的activity並不會總是開啟一個新的任務。詳情請參考 解開Android應用程式組件Activity的"singleTask"之謎,在本文後面也會通過樣本來進行驗證。

singleInstance

總是在新的任務中開啟,並且這個新的任務中有且只有這一個執行個體,也就是說被該執行個體啟動的其他activity會自動運行於另一個任務中。當再次啟動該activity的執行個體時,會重用已存在的任務和執行個體。並且會調用這個執行個體的onNewIntent()方法,將Intent執行個體傳遞到該執行個體中。和singleTask相同,同一時刻在系統中只會存在一個這樣的Activity執行個體。

12、NDK是什麼

NDK:NativeDevelopment Kit

AndroidNDK是一個讓開發人員在Android應用中嵌入使用本地代碼編寫的組件的工具集。

Android應用運行在Dalvik虛擬機器中。NDK允許開發人員使用本地代碼語言(例如C和C++)實現應用的部分功能。這樣以代碼重用的形式能夠給某類應用提供方便,而且在某些情況下能提高運行速度(感謝老婆的協助)。

13、請解釋下Android程式運行時許可權與檔案系統許可權的區別答:運行時許可權Dalvik( android授權)
檔案系統 linux 核心授權

14、橫豎屏切換時候activity的生命週期?1、不設定Activity的android:configChanges時,切屏會重新調用各個生命週期,切橫屏時會執行一次,切豎屏時會執行兩次

2、設定Activity的android:configChanges="orientation"時,切屏還是會重新調用各個生命週期,切橫、豎屏時只會執行一次

3、設定Activity的android:configChanges="orientation|keyboardHidden"時,切屏不會重新調用各個生命週期,只會執行onConfigurationChanged方法15、如何設定Android應用為系統應用

1 將自己的應用方到android原始碼的packages/apps/目錄下,添加Android.mk檔案
2 在應用程式的AndroidManifest.xml中的manifest節點中加入android:sharedUserId="android.uid.system"這個屬性。
3 修改Android.mk檔案,加入LOCAL_CERTIFICATE:= platform這一行
4 使用mm命令來編譯,產生的apk就有同system一樣的許可權了。
5 在android根目錄下用make snod重建system.img
6 啟動emulator運行下應用看看是否好了。

16、如何將SQLite資料庫(dictionary.db檔案)與apk檔案一起發布?可以將dictionary.db檔案複製到Eclipse Android工程中的res aw目錄中。所有在res aw目錄中的檔案不會被壓縮,這樣可以直接提取該目錄中的檔案。可以將dictionary.db檔案複製到res aw目錄中
17.如何將開啟res aw目錄中的資料庫檔案?
解答:在Android中不能直接開啟resaw目錄中的資料庫檔案,而需要在程式第一次啟動時將該檔案複製到手機記憶體或SD卡的某個目錄中,然後再開啟該資料庫檔案。複製的基本方法是使用getResources().openRawResource方法獲得res aw目錄中資源的 InputStream對象,然後將該InputStream對象中的資料寫入其他的目錄中相應檔案中。在Android SDK中可以使用SQLiteDatabase.openOrCreateDatabase方法來開啟任意目錄中的SQLite資料庫檔案。18、線程中wait和sleep的區別答:wait釋放線程鎖,sleep不是線程鎖,wait不佔用系統資源sleep佔用資源

19、兩種方法註冊broadcaseReceiver,及區別。

答:動態註冊和靜態註冊一個BroadcastReceiver的區別:

動態註冊較靜態註冊靈活。實驗證明:當靜態註冊一個BroadcastReceiver時,不論應用程式是啟動與否。都可以接受對應的廣播。

動態註冊的時候,如果不執行unregisterReceiver();方法取消註冊,跟靜態是一樣的。但是如果執行該方法,當執行過以後,就不能接受廣播了。

20、在android中,請簡述jni的調用過程。

1)安裝和下載Cygwin,下載 Android NDK
2)在ndk項目中JNI介面的設計
3)使用C/C++實現本地方法
4)JNI產生動態連結程式庫.so檔案
5)將動態連結程式庫複製到java工程,在java工程中調用,運行java工程即可
21、簡述Android應用程式結構是哪些?

Android應用程式結構是:
Linux Kernel(Linux核心)、

Libraries(系統運行庫或者是c/c++核心庫)、

Application Framework(開發架構套件)、

Applications (核心應用程式)
22、請繼承SQLiteOpenHelper實現:

1).建立一個版本為1的“diaryOpenHelper.db”的資料庫,
2).同時建立一個 “diary” 表(包含一個_id主鍵並自增長,topic字元型100
長度, content字元型1000長度)
3).在資料庫版本變化時請刪除diary表,並重新建立出diary表。

publicclass DBHelper extendsSQLiteOpenHelper{

public final static String DATABASENAME ="diaryOpenHelper.db";
public final static int DATABASEVERSION =1;

//建立資料庫
public DBHelper(Context context,Stringname,CursorFactory factory,int version)
{
super(context, DATABASENAME, factory, DATABASEVERSION);
}
//建立表等機構性檔案
public void onCreate(SQLiteDatabase db)
{
String sql ="create tablediary"+
"("+
"_idinteger primary key autoincrement,"+
"topicvarchar(100),"+
"contentvarchar(1000)"+
")";
db.execSQL(sql);
}
//若資料庫版本有更新,則調用此方法
public void onUpgrade(SQLiteDatabasedb,int oldVersion,int newVersion)
{

String sql = "drop table ifexists diary";
db.execSQL(sql);
this.onCreate(db);
}
}

23、頁面上現有ProgressBar控制項progressBar,請用書寫線程以10秒的的時間完成其進度顯示工作。
publicclass ProgressBarStu extends Activity {

private ProgressBar progressBar = null;
protected void onCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.progressbar);
//從這到下是關鍵
progressBar = (ProgressBar)findViewById(R.id.progressBar);

Thread thread = new Thread(newRunnable() {

@Override
public void run() {
int progressBarMax =progressBar.getMax();
try {
while(progressBarMax!=progressBar.getProgress())
{

intstepProgress = progressBarMax/10;
intcurrentprogress = progressBar.getProgress();
progressBar.setProgress(currentprogress+stepProgress);
Thread.sleep(1000);
}

} catch(InterruptedException e) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}

}
});

thread.start();

//關鍵結束
}

}
24、請描述下Activity的生命週期。

必調用的三個方法:onCreate() --(1)父Activity啟動子Activity,子Actvity退出,父Activity調用順序如下
AAA --< onResume () --< onPause() --< onStop() --(2)使用者點擊Home,Actvity調用順序如下
AAA --< onResume () --< onPause() --< onStop() -- Maybe--(3)調用finish(), Activity調用順序如下
AAA --< onPause() --< onStop() --< onDestroy()
(4)在Activity上顯示dialog,Activity調用順序如下
AAA
(5)在父Activity上顯示透明的或非全屏的activity,Activity調用順序如下
AAA --< onResume () --< onPause()
(6)裝置進入睡眠狀態,Activity調用順序如下
AAA --< onFreeze() --< onPause()
25、如果背景Activity由於某原因被系統回收了,如何在被系統回收之前儲存目前狀態?

在oncreate中寫如下取得儲存的狀態:

1. if (savedInstanceState != null

2. && savedInstanceState.getInt("currentposition") != 0) {

3.

4. videoView.seekTo(savedInstanceState.getInt("currentposition"));

5. }

重寫這個方法儲存狀態

6. protected void onSaveInstanceState(Bundle outState) {

7. // TODO Auto-generated method stub

8. outState.putInt("currentposition", videoView.getCurrentPosition());

9. Log.v("tag", "onSaveInstanceState");

10. super.onSaveInstanceState(outState);

11. }


當你的程式中某一個Activity A在運行時,主動或被動地運行另一個新的Activity B,這個時候A會執行onSaveInstanceState()。B完成以後又會來找A,這個時候就有兩種情況:一是A被回收,二是A沒有被回收,被回收的A就要重新調用onCreate()方法,不同於直接啟動的是這回onCreate()裡是帶上了參數savedInstanceState;而沒被收回的就直接執行onResume(),跳過onCreate()了。
26、如何將一個Activity設定成視窗的樣式。

在AndroidManifest.xml 中定義Activity的地方一句話android:theme="@android:style/Theme.Dialog"或android:theme="@android:style/Theme.Translucent"就變成半透明的
27、如何退出Activity?如何安全退出已調用多個Activity的Application?

對於單一Activity的應用來說,退出很簡單,直接finish()即可。
當然,也可以用killProcess()和System.exit()這樣的方法。

28、請介紹下ContentProvider是如何?資料共用的。

建立一個屬於你自己的Content provider或者將你的資料添加到一個已經存在的Contentprovider中,前提是有相同資料類型並且有寫入Contentprovider的許可權。

29、請解釋下在單執行緒模式中Message、Handler、MessageQueue、Looper之間的關係。

Handler簡介:
一個Handler允許你發送和處理Message和Runable對象,這些對象和一個線程的MessageQueue相關聯。每一個線程執行個體和一個單獨的線程以及該線程的MessageQueue相關聯。當你建立一個新的Handler時,它就和建立它的線程綁定在一起了。這裡,線程我們也可以理解為線程的MessageQueue。從這一點上來看,Handler把Message和Runable對象傳遞給MessageQueue,而且在這些對象離開MessageQueue時,Handler負責執行他們。

Handler有兩個主要的用途:

(1)確定在將來的某個時間點執行一個或者一些Message和Runnable對象。

(2)在其他線程(不是Handler綁定線程)中排入一些要執行的動作。

Scheduling Message,即(1),可以通過以下方法完成:
post(Runnable):Runnable在handler綁定的線程上執行,也就是說不建立新線程。
postAtTime(Runnable,long):
postDelayed(Runnable,long):
sendEmptyMessage(int):
sendMessage(Message):
sendMessageAtTime(Message,long):
sendMessageDelayed(Message,long):
post這個動作讓你把Runnable對象排入MessageQueue,MessageQueue受到這些訊息的時候執行他們,當然以一定的排序。sendMessage這個動作允許你把Message對象排成隊列,這些Message對象包含一些資訊,Handler的hanlerMessage(Message)會處理這些Message.當然,handlerMessage(Message)必須由Handler的子類來重寫。這是編程人員需要作的事。

當posting或者sending到一個Hanler時,你可以有三種行為:當MessageQueue準備好就處理,定義一個延遲時間,定義一個精確的時間去處理。後兩者允許你實現timeout,tick,和基於時間的行為。

當你的應用建立一個新的進程時,主線程(也就是UI線程)內建一個MessageQueue,這個MessageQueue管理頂層的應用對象(像activities,broadcastreceivers等)和主線程建立的表單。你可以建立自己的線程,並通過一個Handler和主線程進行通訊。這和之前一樣,通過post和sendmessage來完成,差別在於在哪一個線程中執行這麼方法。在恰當的時候,給定的Runnable和Message將在Handler的MessageQueue中被Scheduled。


Message簡介:
Message類就是定義了一個資訊,這個資訊中包含一個描述符和任意的資料對象,這個資訊被用來傳遞給Handler.Message對象提供額外的兩個int域和一個Object域,這可以讓你在大多數情況下不用作分配的動作。
儘管Message的建構函式是public的,但是擷取Message執行個體的最好方法是調用Message.obtain(),或者Handler.obtainMessage()方法,這些方法會從回收對象池中擷取一個。


MessageQueue簡介:
這是一個包含message列表的底層類。Looper負責分發這些message。Messages並不是直接加到一個MessageQueue中,而是通過MessageQueue.IdleHandler關聯到Looper。
你可以通過Looper.myQueue()從當前線程中擷取MessageQueue。


Looper簡介:
Looper類被用來執行一個線程中的message迴圈。預設情況,沒有一個訊息迴圈關聯到線程。線上程中調用prepare()建立一個Looper,然後用loop()來處理messages,直到迴圈終止。

大多數和message loop的互動是通過Handler。

下面是一個典型的帶有Looper的線程實現。
class LooperThread extends Thread {
public Handler mHandler;

public void run() {
Looper.prepare();

mHandler = new Handler() {
publicvoidhandleMessage(Message msg) {
// processincomingmessages here
}
};

Looper.loop();
}
}
30、系統上安裝了多種瀏覽器,能否指定某瀏覽器訪問指定頁面?請說明原由。

通過直接發送Uri把參數帶過去,或者通過manifest裡的intentfilter裡的data屬性

31、什麼是ANR如何避免它?

ANR:ApplicationNotResponding,五秒

在Android中,Active Manager和視窗管理器這兩個系統服務負責監視應用程式的響應。當出現下列情況時,Android就會顯示ANR對話方塊了:

對輸入事件(如按鍵、觸控螢幕事件)的響應超過5秒

意向接受器(intentReceiver)超過10秒鐘仍未執行完畢

Android應用程式完全運行在一個獨立的線程中(例如main)。這就意味著,任何在主線程中啟動並執行,需要消耗大量時間的操作都會引發ANR。因為此時,你的應用程式已經沒有機會去響應輸入事件和意向廣播(Intentbroadcast)。

因此,任何運行在主線程中的方法,都要儘可能的只做少量的工作。特別是活動生命週期中的重要方法如onCreate()和 onResume()等更應如此。潛在的比較耗時的操作,如訪問網路和資料庫;或者是開銷很大的計算,比如改變位元影像的大小,需要在一個單獨的子線程中完成(或者是使用非同步請求,如資料庫操作)。但這並不意味著你的主線程需要進入阻塞狀態已等待子線程結束 -- 也不需要調用Therad.wait()或者Thread.sleep()方法。取而代之的是,主線程為子線程提供一個控制代碼(Handler),讓子線程在即將結束的時候調用它(xing:可以參看Snake的例子,這種方法與以前我們所接觸的有所不同)。使用這種方法涉及你的應用程式,能夠保證你的程式對輸入保持良好的響應,從而避免因為輸入事件超過5秒鐘不被處理而產生的ANR。這種實踐需要應用到所有顯示使用者介面的線程,因為他們都面臨著同樣的逾時問題

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.