android面試題-簡答題(一)

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

答:Android的CPU分配的最小單元是線程,Handler通常是在某個線程裏建立的,於是Handler和Thread就是相互綁定的,一一對應。而Runnable是一個接口,Thread是Runnable的子類。因此說,他倆都算一個進程。HandlerThread顧名思義就是能夠處理消息循環的線程,他是一個擁有Looper的線程,能夠處理消息循環。與其說Handler和一個線程綁定,不如說Handler是和Looper一一對應的。最後須要說明的是,在UI線程(主線程)中:   mHandler=new Handler(); java

mHandler.post(new Runnable(){linux

  void run(){android

  //執行代碼...}c++

  });web

  這個線程實際上是在UI線程以內運行的,並無新建線程。sql

  常見的新建線程的方法是:數據庫

  Thread thread = new Thread();編程

  thread.start();瀏覽器

  HandlerThread thread = newHandlerThread("string");

  thread.start();

二、如何設定應用程序爲系統級別的應用?

答: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",這樣也是保護了系統的安全。

三、談談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接口的能力

四、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目錄下建立對應的應用數據目錄。

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

五、如何作適配

1)android有H、L、M、X、XX四個不一樣的文件夾存放不一樣分辨率的圖片,系統會自動加載

2) 偏移量d的設置能夠在values-hpdi,values-mdpi,values-ldpi三種文件夾中的dimens.xml文件進行設置

值得一提的是:

    <dimen name=「bitmap_common_topoffset」>40dp</dimen>

    <dimen name=「bitmap_common_bottomoffset」>-14dp</dimen>

這裏的負數是徹底起做用的,系統會認爲它是一個負值

3)各大手機廠商對於Android操做系統都有或多或少的改動,固然這些改動會對咱們應用程序產生某些影響

 好比:

  (1)系統源代碼中鏈接music服務的aidl文件所在包名:com.android.music 

  (2)LG則可能將該aidl文件修改所在的包(例如修改成 com.android.music.player),而且修改其中的文件內容(增長一個方法,或者減小几個方法,或者修改方法名稱)那麼咱們的應用要想在LG的手機上發佈,那麼咱們就必須改變所要鏈接的aidl文件,必須跟LG廠商修改的徹底一致。

 

六、是否進行過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直接編譯到庫裏(固然內存可能就大了),這種方式能夠本身考慮。

 

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

Tween動畫

        又稱「補間動畫」、「中間動畫」,最先接觸Tween類是在學習Flash時候,使用ActionScript作動畫的時候,使用過類Tween。

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

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

Frame動畫

       又稱幀動畫,主要顯示方式是<animation-list>爲動畫的總標籤,這裏面放着幀動畫<item>標籤,也就是說若干<item>標籤的幀 組合在一塊兒就是幀動畫了。<animation-list > 標籤中android:oneshot="false"這是一個很是重要的屬性,默認爲false 表示 動畫循環播放, 若是這裏寫true 則表示動畫只播發一次。 <item>標籤中記錄着每一幀的信息android:drawable="@drawable/a"表示這一幀用的圖片爲"a",下面以此類推。 android:duration="100" 表示這一幀持續100毫秒,能夠根據這個值來調節動畫播放的速度。

 

 八、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類,代碼以下:
<!-- 註冊服務 --> 
<service android:name=".MyService"> 
  <intent-filter> 
   <!--  指定調用AIDL服務的ID  --> 
      <actionandroid:name="net.blogjava.mobile.aidlservice.RemoteService"/> 
   </intent-filter> 
</service>
爲何要指定調用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類的內部類的對象。

九、Android系統中GC什麼狀況下不會出現內存泄露

1. 數據庫的cursor沒有關閉

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

3.Bitmap對象不使用時採用recycle()釋放內存

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

 

十、什麼狀況會致使Force Close ?如何避免?可否捕獲致使其的異常?
答:通常像空指針啊,能夠看起logcat,而後對應到程序中 來解決錯誤

十一、activity的4種模式,以及不一樣模式的做用。

http://blog.csdn.net/zhangjg_blog/article/details/10923643

activity有四種啓動模式,分別爲standard,singleTop,singleTask,singleInstance。若是要使用這四種啓動模式,必須在manifest文件中<activity>標籤中的launchMode屬性中配置,如:

<activity android:name=".app.InterstitialMessageActivity"  
          android:label="@string/interstitial_label"  
          android:theme="@style/Theme.Dialog"  
          android:launchMode="singleTask"  
</activity> 

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

谷歌的官方文檔上稱,若是一個activity的啓動模式爲singleTask,那麼系統總會在一個新任務的最底部(root)啓動這個activity,而且被這個activity啓動的其餘activity會和該activity同時存在於這個新任務中。若是系統中已經存在這樣的一個activity則會重用這個實例,而且調用他的onNewIntent()方法。即,這樣的一個activity在系統中只會存在一個實例。

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

singleInstance

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

 

十二、NDK是什麼

NDK:NativeDevelopment Kit

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

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

 

1三、請解釋下Android程序運行時權限與文件系統權限的區別

答:運行時權限Dalvik( android受權) 
    文件系統 linux 內核受權

1四、橫豎屏切換時候activity的生命週期?

一、不設置Activity的android:configChanges時,切屏會從新調用各個生命週期,切橫屏時會執行一次,切豎屏時會執行兩次 

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

三、設置Activity的android:configChanges="orientation|keyboardHidden"時,切屏不會從新調用各個生命週期,只會執行onConfigurationChanged方法

1五、如何設定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運行下應用看看是否好了。 

1六、如何將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數據庫文件。

1八、線程中wait和sleep的區別

答:wait釋放線程鎖,sleep不是線程鎖,wait不佔用系統資源sleep佔用資源

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

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

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

動態註冊的時候,若是不執行unregisterReceiver();方法取消註冊,跟靜態是同樣的。可是若是執行該方法,當執行過之後,就不能接受廣播了。

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

1)安裝和下載Cygwin,下載 Android NDK
2)在ndk項目中JNI接口的設計
3)使用C/C++實現本地方法
4)JNI生成動態連接庫.so文件
5)將動態連接庫複製到java工程,在java工程中調用,運行java工程便可
2一、簡述Android應用程序結構是哪些?

Android應用程序結構是:
Linux Kernel(Linux內核)、

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

Application Framework(開發框架包)、

Applications (核心應用程序)
2二、請繼承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);
}
}

2三、頁面上現有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();

//關鍵結束
}

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

必調用的三個方法:onCreate() --<onStart() --< onResume(),用AAA表示
(1)父Activity啓動子Activity,子Actvity退出,父Activity調用順序以下
AAA --< onResume () --< onPause() --< onStop() --<onRestart()--< onStart(),onResume() …
(2)用戶點擊Home,Actvity調用順序以下
AAA --< onResume () --< onPause() --< onStop() -- Maybe--<onDestroy() – 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()
2五、若是後臺的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()了。 
2六、如何將一個Activity設置成窗口的樣式。

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

對於單一Activity的應用來講,退出很簡單,直接finish()便可。
固然,也能夠用killProcess()和System.exit()這樣的方法。

2八、請介紹下ContentProvider是如何實現數據共享的。

建立一個屬於你本身的Content provider或者將你的數據添加到一個已經存在的Contentprovider中,前提是有相同數據類型而且有寫入Contentprovider的權限。

2九、請解釋下在單線程模型中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屬性

3一、什麼是ANR如何避免它?

ANR:ApplicationNotResponding,五秒 在Android中,活動管理器和窗口管理器這兩個系統服務負責監視應用程序的響應。當出現下列狀況時,Android就會顯示ANR對話框了: 對輸入事件(如按鍵、觸摸屏事件)的響應超過5秒 意向接受器(intentReceiver)超過10秒鐘仍未執行完畢 Android應用程序徹底運行在一個獨立的線程中(例如main)。這就意味着,任何在主線程中運行的,須要消耗大量時間的操做都會引起ANR。由於此時,你的應用程序已經沒有機會去響應輸入事件和意向廣播(Intentbroadcast)。 所以,任何運行在主線程中的方法,都要儘量的只作少許的工做。特別是活動生命週期中的重要方法如onCreate()和 onResume()等更應如此。潛在的比較耗時的操做,如訪問網絡和數據庫;或者是開銷很大的計算,好比改變位圖的大小,須要在一個單獨的子線程中完成(或者是使用異步請求,如數據庫操做)。但這並不意味着你的主線程須要進入阻塞狀態已等待子線程結束 -- 也不須要調用Therad.wait()或者Thread.sleep()方法。取而代之的是,主線程爲子線程提供一個句柄(Handler),讓子線程在即將結束的時候調用它(xing:能夠參看Snake的例子,這種方法與之前咱們所接觸的有所不一樣)。使用這種方法涉及你的應用程序,可以保證你的程序對輸入保持良好的響應,從而避免由於輸入事件超過5秒鐘不被處理而產生的ANR。這種實踐須要應用到全部顯示用戶界面的線程,由於他們都面臨着一樣的超時問題

相關文章
相關標籤/搜索