4,, 在onCreate方法中Bundle savedInstanceState 這個參數(shù)有什么作用? 在onCreate方法中有saveInstanceState這個參數(shù),,其實這個參數(shù)對應兩個方法,。 void onSaveInstanceState(Bundle outState);void onRestoreInstanceState(Bundle savedInstanceState),。當某個activity變得“容易”被系統(tǒng)銷毀時,,說白了就是系統(tǒng)在內(nèi)存不足或者其他異常情況下把你的Activity銷毀時,將調(diào)用這個方法,。需要注意的是它是系統(tǒng)調(diào)用的,,并且你的Activity是被動得被銷毀。你可以在銷毀的時候保存一下數(shù)據(jù),。然后在onCreate方法中拿出來,。那什么情況下能觸發(fā)這兩個方法呢? 1),、當用戶按下HOME鍵時,。 這是顯而易見的,系統(tǒng)不知道你按下HOME后要運行多少其他的程序,,自然也不知道activity A是否會被銷毀,,故系統(tǒng)會調(diào)用onSaveInstanceState,讓用戶有機會保存某些非永久性的數(shù)據(jù),。以下幾種情況的分析都遵循該原則 2),、長按HOME鍵,選擇運行其他的程序時,。 3),、按下電源按鍵(關閉屏幕顯示)時。 4)、從activity A中啟動一個新的activity時,。 5),、屏幕方向切換時,例如從豎屏切換到橫屏時,。 在屏幕切換之前,,系統(tǒng)會銷毀activity A,在屏幕切換之后系統(tǒng)又會自動地創(chuàng)建activity A,,所以onSaveInstanceState一定會被執(zhí)行
總而言之,,onSaveInstanceState的調(diào)用遵循一個重要原則,即當系統(tǒng)“未經(jīng)你許可”時銷毀了你的activity,,則onSaveInstanceState會被系統(tǒng)調(diào)用,,這是系統(tǒng)的責任,因為它必須要提供一個機會讓你保存你的數(shù)據(jù)(當然你不保存那就隨便你了),。
至于onRestoreInstanceState方法,,需要注意的是,onSaveInstanceState方法和onRestoreInstanceState方法“不一定”是成對的被調(diào)用的,,onRestoreInstanceState被調(diào)用的前提是,,activity A“確實”被系統(tǒng)銷毀了,而如果僅僅是停留在有這種可能性的情況下,,則該方法不會被調(diào)用,,例如,當正在顯示activity A的時候,,用戶按下HOME鍵回到主界面,,然后用戶緊接著又返回到activity A,這種情況下activity A一般不會因為內(nèi)存的原因被系統(tǒng)銷毀,,故activity A的onRestoreInstanceState方法不會被執(zhí)行
另外,,onRestoreInstanceState的bundle參數(shù)也會傳遞到onCreate方法中,你也可以選擇在onCreate方法中做數(shù)據(jù)還原,。
5,, 談談你對BroadCastRceiver的理解? 廣播接收者,,android四大組件之一,,也是唯一一個能動態(tài)注冊的組件。 1)廣播接收者是一個專注于接收廣播通知信息,,并做出對應處理的組件,。很多廣播是源自于系統(tǒng)──比如,通知時區(qū)改變,、電池電量低,、拍攝了一張照片或者用戶改變了語言選項,。應用程序也可以進行廣播──比如說,通知其它應用程序一些數(shù)據(jù)下載完成并處于可用狀態(tài),。 2)應用程序可以擁有任意數(shù)量的廣播接收者以對所有它感興趣的通知信息予以響應,。所有的接收器均繼承自BroadcastReceiver基類。 3)廣播接收者沒有用戶界面,。然而,,它們可以啟動一個activity來響應它們收到的信息,或者用NotificationManager來通知用戶,。通知可以用很多種方式來吸引用戶的注意力──閃動背燈、震動,、播放聲音等等,。一般來說是在狀態(tài)欄上放一個持久的圖標,用戶可以打開它并獲取消息,。 6,, 廣播分幾種?他們有什么區(qū)別,? 廣播被分為兩種不同的類型:“普通廣播(Normal broadcasts)”和“有序廣播(Ordered broadcasts)”,。普通廣播是完全異步的,可以在同一時刻(邏輯上)被所有接收者接收到,,消息傳遞的效率比較高,,但缺點是:接收者不能將處理結(jié)果傳遞給下一個接收者,并且無法終止廣播Intent的傳播,。 然而有序廣播是按照接收者聲明的優(yōu)先級別,,被接收者依次接收廣播。如:A的級別高于B,B的級別高于C,那么,,廣播先傳給A,,再傳給B,最后傳給C ,。優(yōu)先級別聲明在 intent-filter 元素的 android:priority 屬性中,,數(shù)越大優(yōu)先級別越高,取值范圍:-1000到1000,優(yōu)先級別也可以調(diào)用IntentFilter對象的setPriority()進行設置 ,。有序廣播的接收者可以終止廣播Intent的傳播,,廣播Intent的傳播一旦終止,后面的接收者就無法接收到廣播,。
另外,,有序廣播的接收者可以將數(shù)據(jù)傳遞給下一個接收者,如:A得到廣播后,,可以往它的結(jié)果對象中存入數(shù)據(jù),,當廣播傳給B時,B可以從A的結(jié)果對象中得到A存入的數(shù)據(jù),。
Context.sendBroadcast()
發(fā)送的是普通廣播,所有訂閱者都有機會獲得并進行處理,。
Context.sendOrderedBroadcast()
發(fā)送的是有序廣播,,系統(tǒng)會根據(jù)接收者聲明的優(yōu)先級別按順序逐個執(zhí)行接收者, 前面的接收者有權(quán)終止廣播(BroadcastReceiver.abortBroadcast()),,如果廣播被前面的接收者終止,,后面的接收者就再也無法獲取到廣播。對于有序廣播,,前面的接收者可以將數(shù)據(jù)通過setResultExtras(Bundle)方法存放進結(jié)果對象,,然后傳給下一個接收者,下一個接收者通過代碼:Bundle bundle = getResultExtras(true))可以獲取上一個接收者存入在結(jié)果對象中的數(shù)據(jù),。
7,, 廣播的生命周期? 廣播的生命周期是非常短的,,當發(fā)送之后intent會到AndroidManifest.xml文件中找是不是有匹配的action,,如果有就會調(diào)用Receiver ,然后獲得Receiver 對象,,再執(zhí)行onReceive方法,,這時候Receiver對象就沒有用了,當我們再次點擊按鈕的時候就會重新獲得對象,,這就是BroadcastReceiver的生命周期. 在BroadcastReceiver里不能做一些比較耗時的操作,否側(cè)會彈出ANR(Application No Response)的對話框. 如果需要完成一項比較耗時的工作,應該通過發(fā)送Intent給Service,由Service來完成.這里不能使用子線程來解決,因為BroadcastReceiver的生命周期很短,子線程可能還沒有結(jié)束,,BroadcastReceiver就先結(jié)束了.BroadcastReceiver一旦結(jié)束,此時BroadcastReceiver的所在進程很容易在系統(tǒng)需要內(nèi)存時被優(yōu)先殺死,因為它屬于空進程(沒有任何活動組件的進程).如果它的宿主進程被殺死,那么正在工作的子線程也會被殺死.所以采用子線程來解決是不可靠的. 8, 兩種注冊BroadcastReceiver的方法,? 使用在manifest中注冊的方法注冊BroadcastReceiver,,即使你的應用程序沒有啟動,或者已經(jīng)被關閉,,這個BroadcastReceiver依然會繼續(xù)運行,,這樣的運行機制可能會給軟件的用戶造成困擾。所以作為程序的開發(fā)者,,我們希望能夠有一種靈活的機制完成BroadcastReceiver的綁定和解除綁定操作,。Android當然也考慮到了這些問題,所以在Context這個類當中提供了如下兩個函數(shù)可以在代碼中注冊:
i. registerReceiver(receiver,filter); 這個函數(shù)的作用就是將一個BroadcastReceiver注冊到應用程序當中,,這個函數(shù)接收兩個參數(shù),,第一個參數(shù)是需要注冊的BroadcastReceiver對象,第二個是一個IntentFilter,。第一個參數(shù)是非常容易理解的,,第二個參數(shù)的作用是定義了哪些Intent才能觸發(fā)這個注冊的BroadcastReceiver對象。
ii. unregisterReceiver(receiver); 這個方法就非常的簡單了,,用于解除BroadcastReceiver的綁定狀態(tài),。一旦解除完成,,響應的BroadcastReceiver就不會再接收系統(tǒng)所廣播的Intent了。
兩種注冊BroadcastReceiver的方法
1.在應用程序的代碼中進行注冊 注冊BroadcastReceiver registerReceiver(receiver,filter); 取消注冊BroadcastReceiver unregisterReceiver(receiver); 2.在AndroidManifest.xml當中進行注冊
<receiver android:name="SMSReceiver"> <intent-filter> <action android:name="android.provider.Telephony.SMS_RECEIVED" /> </intent-filter> </receiver>
兩種注冊BroadcastReceiver方法的比較: 現(xiàn)在我們了解了兩種注冊BroadcastReceiver的方法之后,,需要考慮一下這兩種方法適用的場合:
i. 第一種注冊的方法可以保證在應用程序安裝之后,,BroadcastReceiver始終處于活動狀態(tài),通常用于監(jiān)聽系統(tǒng)狀態(tài)的改變,,比如說手機的電量,,wifi網(wǎng)卡的狀態(tài)(當然,監(jiān)視這些東西也是取決于軟件的需求),。對于這樣的BroadcastReceiver,,通常是在產(chǎn)生某個特定的系統(tǒng)事件之后,進行相應的操作,,比如說wifi網(wǎng)卡打開時,,給用戶一個提示;
ii. 第二種注冊方法相對第一種要靈活的多,,這樣注冊的BroadcastReceiver通常用于更新UI的狀態(tài)。一般來說,,都是在一個Activity啟動的時候使用這樣的方法注冊BroadcastReceiver,,一旦接收到廣播的事件,就可以在onReceive方法當中更新當前的這個Activity當中的控件,。但是需要注意的是如果這個Activity不可見了,,就應該調(diào)用unregisterReceiver方法來解除注冊 9, 粘性廣播有什么作用,?怎么使用,? 粘性廣播主要為了解決,在發(fā)送完廣播之后,,動態(tài)注冊的接收者,,也能夠收到廣播。舉個例子首先發(fā)送一廣播,,我的接收者是通過程序中的某個按鈕動態(tài)注冊的,。如果不是粘性廣播,我注冊完接收者肯定無法收到廣播了,。這是通過發(fā)送粘性廣播就能夠在我動態(tài)注冊接收者后也能收到廣播,。 用法: //發(fā)送粘性廣播 Public void sendStickyBroadCast(){ Intent intent=new Intent(); intent.setAction(“com.iteye.myreceiver.action”); intent.putExtra(“name”,”tom”); this.sendStickyBroadCast(intent);
} 發(fā)送粘性廣播還需要發(fā)送粘性廣播的權(quán)限:<uses-permission android:name="android.permission.BROADCAST_STICKY" /> //動態(tài)注冊廣播接收者 MyReceiver mr = new MyReceiver (); IntentFilter filter = new IntentFilter(); filter.addAction("com.iteye.myreceiver.action "); filter.addCategory(Intent.CATEGORY_DEFAULT); Intent ii = this.registerReceiver(mr, filter); String n = ii.getStringExtra("name"); Toast.makeText(this, "動態(tài)注冊接收者完成,收到粘性廣播,name=" + n, 1).show(); 10,如何控制接收者或者發(fā)送方得權(quán)限,? 1)如果廣播發(fā)送方要求接收方必須有某個權(quán)限才能收到廣播怎么做呢,? /** * 發(fā)送廣播,指定接收者權(quán)限 * sendBroadcast(i, "com.iteye.permission.receiver");//指定接收者權(quán)限 */ public void sendBroadcast() { //隱式意圖,發(fā)送廣播 Intent i = new Intent(); i.setAction("com.iteye.receiver.action"); i.putExtra("name", "tom"); this.sendBroadcast(i, " com.iteye.permission.receiver "); Log.i("Other",".send ok!"); } 在清單文件里receiver必須有這個權(quán)限才能收到廣播。 首先,,需要定義權(quán)限:<permission android:name=" com.iteye.permission.receiver " /> 然后,,聲明權(quán)限:<uses-permission android:name=" com.iteye.permission.receiver " /> 這時接收者就能收到發(fā)送的廣播,。 2)反過來,如果接收者要求發(fā)送方必須擁有某個權(quán)限,,我才接收你的廣播怎么辦呢,? <!-- 注冊廣播接收者 android:permission:控制發(fā)送方需要具備指定權(quán)限,才接收其廣播. --> <receiver android:name=".MyReceiver" android:permission="com.permission.sender"> <intent-filter android:priority="100"> <action android:name="com.iteye.receiver.action" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver> 即使過濾器匹配,如果發(fā)送方?jīng)]有相應權(quán)限,,接收者也不會接收其廣播,。 |
|