Android四大組件【轉(zhuǎn)】

Android四大組件 --- Activity

Activity生命周期

生命周期:onCreate() -> onStart() - > onResume() -> onPause() -> onStop() -> onDestroy()

Paste_Image.png
  • 啟動(dòng)activity:系統(tǒng)先調(diào)用onCreate()掰读,然后調(diào)用onStart()蛆橡,最后調(diào)用onResume()方法,activity進(jìn)入運(yùn)行狀態(tài)。
  • activity被其他activity覆蓋其上(DialogActivity)或者鎖屏:系統(tǒng)會(huì)調(diào)用onPause()方法,暫停當(dāng)前activity的執(zhí)行。
  • 當(dāng)前activity由被覆蓋狀態(tài)回到前臺(tái)或者解鎖屏:系統(tǒng)會(huì)調(diào)用onResume()方法脂崔,再次進(jìn)入運(yùn)行狀態(tài)。
  • 當(dāng)前Activity轉(zhuǎn)到新的Activity界面或按Home鍵回到主屏梧喷,自身退居后臺(tái):系統(tǒng)會(huì)先調(diào)用onPause方法砌左,然后調(diào)用onStop方法,進(jìn)入停滯狀態(tài)铺敌。

  • 用戶后退回到此Activity:系統(tǒng)會(huì)先調(diào)用onRestart方法汇歹,然后調(diào)用onStart方法,最后調(diào)用onResume方法偿凭,再次進(jìn)入運(yùn)行狀態(tài)产弹。

  • 當(dāng)前Activity處于被覆蓋狀態(tài)或者后臺(tái)不可見(jiàn)狀態(tài),即第2和第4步弯囊,系統(tǒng)內(nèi)存不足痰哨,殺死當(dāng)前Activity,而后用戶退回當(dāng)前Activity:再次調(diào)用onCreate方法匾嘱、onStart方法斤斧、onResume方法,進(jìn)入運(yùn)行狀態(tài)霎烙。

  • 用戶退出當(dāng)前Activity:系統(tǒng)先調(diào)用onPause方法撬讽,然后調(diào)用onStop方法蕊连,最后調(diào)用onDestory方法,結(jié)束當(dāng)前Activity游昼。

  • onRestart():表示activity正在重新啟動(dòng) 甘苍,一般情況下,當(dāng)前activity從不可見(jiàn)重新變成可見(jiàn)狀態(tài)時(shí)烘豌,onRestart()就會(huì)被調(diào)用羊赵,這種情形一般是用戶行為所導(dǎo)致的,比如用戶按HOME鍵切換到桌面然后重新打開(kāi)APP或者按back鍵扇谣。

  • onStart():activity可見(jiàn)了昧捷,但是還沒(méi)有出現(xiàn)在前臺(tái),還無(wú)法和用戶交互罐寨。

  • onPause():表示activity正在停止靡挥,此時(shí)可以做一些存儲(chǔ)數(shù)據(jù),停止動(dòng)畫(huà)等工作鸯绿,注意不能太耗時(shí)跋破,因?yàn)檫@會(huì)影響到新activity的顯示,onPause必須先執(zhí)行完瓶蝴,新的activity的onResume才會(huì)執(zhí)行毒返。

  • 從activity是否可見(jiàn)來(lái)說(shuō),onstart()和onStop()是配對(duì)的舷手,從activity是否在前臺(tái)來(lái)說(shuō)拧簸,onResume()和onPause()是配對(duì)的。

  • 舊activity先onPause男窟,然后新activity在啟動(dòng)

注意:當(dāng)activity中彈出dialog對(duì)話框的時(shí)候盆赤,activity不會(huì)回調(diào)onPause。然而當(dāng)activity啟動(dòng)dialog風(fēng)格的activity的時(shí)候歉眷,此activity會(huì)回調(diào)onPause函數(shù)牺六。

異常情況下的生命周期:比如當(dāng)系統(tǒng)資源配置發(fā)生改變以及系統(tǒng)內(nèi)存不足時(shí),activity就可能被殺死汗捡。

  • 情況1:資源相關(guān)的系統(tǒng)配置發(fā)生改變導(dǎo)致activity被殺死并重新創(chuàng)建比如說(shuō)當(dāng)前activity處于豎屏狀態(tài)淑际,如果突然旋轉(zhuǎn)屏幕,由于系統(tǒng)配置發(fā)生了改變扇住,在默認(rèn)情況下春缕,activity就會(huì)被銷毀并且重新創(chuàng)建,當(dāng)然我們也可以組織系統(tǒng)重新創(chuàng)建我們的activity台囱。
Paste_Image.png

系統(tǒng)配置發(fā)生改變以后淡溯,activity會(huì)銷毀读整,其onPause簿训,onStop,onDestory均會(huì)被調(diào)用,由于activity是在異常情況下終止的强品,系統(tǒng)會(huì)調(diào)用onSaveInstance來(lái)保存當(dāng)activity狀態(tài)膘侮,這個(gè)方法的調(diào)用時(shí)機(jī)是在onStop之前。與onPause沒(méi)有既定的時(shí)序關(guān)系的榛,當(dāng)activity重新創(chuàng)建后琼了,系統(tǒng)會(huì)調(diào)用onRestoreInstanceState,并且把a(bǔ)ctivity銷毀時(shí)onSaveInstanceState方法保存的Bundle對(duì)象作為參數(shù)同時(shí)傳遞給onRestoreInstanceState和onCreate方法夫晌。onRestoreInstanceState()onStart()方法后回調(diào)雕薪。

同時(shí),在onSaveInstanceState和onRestoreInstanceState方法中晓淀,系統(tǒng)自動(dòng)為我們做了一些恢復(fù)工作所袁,如:文本框(EditeText)中用戶輸入的數(shù)據(jù),ListView滾動(dòng)的位置等凶掰,這些view相關(guān)的狀態(tài)系統(tǒng)都能夠默認(rèn)為我們恢復(fù)燥爷。可以查看view源碼懦窘,和activity一樣前翎,每個(gè)view都有onSaveInstanceState方法和onRestoreInstanceState方法。

生命周期日志打映┩俊:

04-11 09:44:57.350 11757-11757/cn.hotwoo.play:remote I/MainActivity: onCreate
04-11 09:44:57.354 11757-11757/cn.hotwoo.play:remote I/MainActivity: onStart
04-11 09:44:57.356 11757-11757/cn.hotwoo.play:remote I/MainActivity: onResume
04-11 09:44:57.425 11757-11757/cn.hotwoo.play:remote I/MainActivity: onCreateOptionsMenu
04-11 09:44:59.149 11757-11757/cn.hotwoo.play:remote I/MainActivity: onPause
04-11 09:44:59.151 11757-11757/cn.hotwoo.play:remote I/MainActivity: onSaveInstanceState
04-11 09:44:59.151 11757-11757/cn.hotwoo.play:remote I/MainActivity: onStop
04-11 09:44:59.151 11757-11757/cn.hotwoo.play:remote I/MainActivity: onDestroy
04-11 09:44:59.234 11757-11757/cn.hotwoo.play:remote I/MainActivity: onCreate
04-11 09:44:59.235 11757-11757/cn.hotwoo.play:remote I/MainActivity: onStart
04-11 09:44:59.236 11757-11757/cn.hotwoo.play:remote I/MainActivity: onRestoreInstanceState
04-11 09:44:59.237 11757-11757/cn.hotwoo.play:remote I/MainActivity: onResume
04-11 09:44:59.270 11757-11757/cn.hotwoo.play:remote I/MainActivity: onCreateOptionsMenu
04-11 10:02:32.320 11757-11757/cn.hotwoo.play:remote I/MainActivity: onPause04-11 10:02:32.516 11757-11757/cn.hotwoo.play:remote I/MainActivity: onStop
04-11 10:02:32.516 11757-11757/cn.hotwoo.play:remote I/MainActivity: onDestroy
  • 情況2:資源內(nèi)存不足導(dǎo)致低優(yōu)先級(jí)的activity被殺死
    這里的情況和前面的情況1數(shù)據(jù)存儲(chǔ)和恢復(fù)是完全一致的港华,activity
    按照優(yōu)先級(jí)從高到低可以分為如下三種:
    (1)前臺(tái)activity---正在和用戶交互的activity,優(yōu)先級(jí)最高
    (2)可見(jiàn)但非前臺(tái)activity---比如activity中彈出了一個(gè)對(duì)話框午衰,導(dǎo)致activity可見(jiàn)但是位于后臺(tái)無(wú)法和用戶直接交互苹丸。
    (3)后臺(tái)activity---已經(jīng)被暫停的activity,比如執(zhí)行了onStop苇经,優(yōu)先級(jí)最低赘理。

防止重新創(chuàng)建activity:activity指定configChange屬性來(lái)不讓系統(tǒng)重新創(chuàng)建activity。android : configChanges = "orientation"

Activity與Fragment生命周期關(guān)系

創(chuàng)建過(guò)程:

Paste_Image.png

銷毀過(guò)程:

Paste_Image.png

Activity與menu創(chuàng)建先后順序

在activity創(chuàng)建完回調(diào)onResume后創(chuàng)建menu扇单,回調(diào)onCreateOptionsMenu

04-05 00:35:03.452 2292-2292/cn.hotwoo.play:remote I/MainActivity: onCreate
04-05 00:35:03.453 2292-2292/cn.hotwoo.play:remote I/MainActivity: onStart
04-05 00:35:03.454 2292-2292/cn.hotwoo.play:remote I/MainActivity: onResume
04-05 00:35:03.482 2292-2292/cn.hotwoo.play:remote I/MainActivity: onCreateOptionsMenu

Activity的啟動(dòng)模式

有四種啟動(dòng)模式:standard商模,singleTop,singleTask蜘澜,singleInstance

  • standard模式:在這種模式下施流,activity默認(rèn)會(huì)進(jìn)入啟動(dòng)它的activity所屬的任務(wù)棧中注意:在非activity類型的context(如ApplicationContext)并沒(méi)有所謂的任務(wù)棧鄙信,所以不能通過(guò)ApplicationContext去啟動(dòng)standard模式的activity瞪醋。
  • singleTop模式:棧頂復(fù)用模式。如果新activity位于任務(wù)棧的棧頂?shù)臅r(shí)候装诡,activity不會(huì)被重新創(chuàng)建银受,同時(shí)它的onNewIntent方法會(huì)被回調(diào)践盼。 注意:這個(gè)activity的onCreate,onStart宾巍,onResume不會(huì)被回調(diào)咕幻,因?yàn)樗麄儾](méi)有發(fā)生改變。
  • singleTask模式:棧內(nèi)復(fù)用模式顶霞。只要activity在一個(gè)棧中存在肄程,那么多次啟動(dòng)此activity不會(huì)被重新創(chuàng)建單例,系統(tǒng)會(huì)回調(diào)onNewIntent选浑。比如activityA蓝厌,系統(tǒng)首先會(huì)尋找是否存在A想要的任務(wù)棧,如果沒(méi)有則創(chuàng)建一個(gè)新的任務(wù)棧古徒,然后把a(bǔ)ctivityA壓入棧褂始,如果存在任務(wù)棧,然后再看看有沒(méi)有activityA的實(shí)例描函,如果實(shí)例存在崎苗,那么就會(huì)把A調(diào)到棧頂并調(diào)用它的onNewIntent方法,如果不存在則把它壓入棧舀寓。
  • singleInstance模式:?jiǎn)螌?shí)例模式胆数。這種模式的activity只能單獨(dú)地位于一個(gè)任務(wù)棧中。由于站內(nèi)復(fù)用特性互墓,后續(xù)的請(qǐng)求均不會(huì)創(chuàng)建新的activity實(shí)例必尼。

注意:默認(rèn)情況下,所有activity所需的任務(wù)棧的名字為應(yīng)用的包名篡撵,可以通過(guò)給activity指定TaskAffinity屬性來(lái)指定任務(wù)棧判莉,**這個(gè)屬性值不能和包名相同,否則就沒(méi)有意義 **育谬。


Android四大組件 --- Service

本地服務(wù)(LocalService)

調(diào)用者和service在同一個(gè)進(jìn)程里券盅,所以運(yùn)行在主進(jìn)程的main線程中。所以不能進(jìn)行耗時(shí)操作膛檀,可以采用在service里面創(chuàng)建一個(gè)Thread來(lái)執(zhí)行任務(wù)锰镀。service影響的是進(jìn)程的生命周期,討論與Thread的區(qū)別沒(méi)有意義咖刃。任何 Activity 都可以控制同一 Service泳炉,而系統(tǒng)也只會(huì)創(chuàng)建一個(gè)對(duì)應(yīng) Service 的實(shí)例

兩種啟動(dòng)方式

第一種啟動(dòng)方式:

通過(guò)start方式開(kāi)啟服務(wù).
使用service的步驟:

1嚎杨,定義一個(gè)類繼承service
2花鹅,manifest.xml文件中配置service
3,使用context的startService(Intent)方法啟動(dòng)service
4枫浙,不在使用時(shí)刨肃,調(diào)用stopService(Intent)方法停止服務(wù)

使用start方式啟動(dòng)的生命周期:

onCreate() -- > onStartCommand() -- > onDestory()
注意:如果服務(wù)已經(jīng)開(kāi)啟古拴,不會(huì)重復(fù)回調(diào)onCreate()方法,如果再次調(diào)用context.startService()方法之景,service而是會(huì)調(diào)用onStart()或者onStartCommand()方法斤富。停止服務(wù)需要調(diào)用context.stopService()方法膏潮,服務(wù)停止的時(shí)候回調(diào)onDestory被銷毀锻狗。

特點(diǎn):一旦服務(wù)開(kāi)啟就跟調(diào)用者(開(kāi)啟者)沒(méi)有任何關(guān)系了。開(kāi)啟者退出了焕参,開(kāi)啟者掛了轻纪,服務(wù)還在后臺(tái)長(zhǎng)期的運(yùn)行,開(kāi)啟者不能調(diào)用服務(wù)里面的方法叠纷。

第二種啟動(dòng)方式

采用bind的方式開(kāi)啟服務(wù)
使用service的步驟:

1刻帚,定義一個(gè)類繼承Service
2,在manifest.xml文件中注冊(cè)service
3涩嚣,使用context bindService(Intent,ServiceConnection,int)方法啟動(dòng)service
4崇众,不再使用時(shí),調(diào)用unbindService(ServiceConnection)方法停止該服務(wù)

使用這種start方式啟動(dòng)的service的生命周期如下:

onCreate() -- > onBind() --> onUnbind() -- > onDestory()

注意:綁定服務(wù)不會(huì)調(diào)用onStart()或者onStartCommand()方法

特點(diǎn):bind的方式開(kāi)啟服務(wù)航厚,綁定服務(wù)顷歌,調(diào)用者掛了,服務(wù)也會(huì)跟著掛掉幔睬。綁定者可以調(diào)用服務(wù)里面的方法眯漩。

示例
定義一個(gè)類繼承service

//本地service不涉及進(jìn)程間通信
public class MyService extends Service { 
    private String TAG = "MyService"; 
   
   @Override 
    public void onCreate() { 
    super.onCreate(); 
    Log.i(TAG,"onCreate");
   } 

    @Override 
    public void onStart(Intent intent, int startId) { 
    super.onStart(intent, startId); 
    Log.i(TAG,"onStart");
   } 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
        Log.i(TAG,"onStartCommand"); 
        return super.onStartCommand(intent, flags, startId); 
    } //綁定服務(wù)時(shí)調(diào)用這個(gè)方法,返回一個(gè)IBinder對(duì)象 
    
    @Nullable 
    @Override 
    public IBinder onBind(Intent intent) {     
        Log.i(TAG,"onBind"); 
        return new MyBinder(); 
    } 

    @Override 
    public boolean onUnbind(Intent intent) {         
        Log.i(TAG,"onUnbind"); 
        return super.onUnbind(intent); 
    }

// 停止服務(wù)麻顶,通過(guò)調(diào)用Context.unbindService()赦抖,別忘了service也繼承了Context類
// @Override
// public void unbindService(ServiceConnection conn) {
// super.unbindService(conn);
// Log.i(TAG,"unbindService");
// } 
//服務(wù)掛了 

    @Override 
     public void onDestroy() { 
        super.onDestroy(); Log.i(TAG,"onDestroy"); 
    } 

    public interface MyIBinder{ 
        void invokeMethodInMyService();
     } 

    public class MyBinder extends Binder implements MyIBinder{ 
        public void stopService(ServiceConnection serviceConnection){ 
            unbindService(serviceConnection);
         } 

    @Override 
    public void invokeMethodInMyService() { 
        for(int i =0; i <   20; i ++){ 
        System.out.println("service is opening"); 
    } 
  } 
}

在manifest.xml文件中注冊(cè)service

//Service 必須要注冊(cè) 
<service  android:name=".server.MyService" 
        android:exported="true"> 
        <intent-filter> 
            <action android:name="cn.hotwoo.play.server.MyService"/>     
            <category android:name="android.intent.category.default" /> 
        </intent-filter> 
</service>

綁定自定義的service


Paste_Image.png

Paste_Image.png

startService輸出日志:

04-01 19:56:09.846 22845-22845/cn.hotwoo.play I/MyService: onCreate
04-01 19:56:09.854 22845-22845/cn.hotwoo.play I/MyService: onStartCommand
04-01 19:56:09.854 22845-22845/cn.hotwoo.play I/MyService: onStart

bindService 輸出日志:

04-01 19:53:21.459 14704-14704/cn.hotwoo.play I/MyService: onCreate
04-01 19:53:21.460 14704-14704/cn.hotwoo.play I/MyService: onBind
04-01 19:53:21.461 14704-14704/cn.hotwoo.play I/MyService: onServiceConnected

點(diǎn)擊back鍵關(guān)閉activity或者調(diào)用Context.unbindService()方法后:

04-05 01:16:27.508 11427-11427/cn.hotwoo.play I/MyService: onUnbind
04-05 01:16:27.508 11427-11427/cn.hotwoo.play I/MyService: onDestroy

遠(yuǎn)程服務(wù)

調(diào)用者和service不在同一個(gè)進(jìn)程中,service在單獨(dú)的進(jìn)程中的main線程辅肾,是一種垮進(jìn)程通信方式队萤。學(xué)習(xí)地址

綁定遠(yuǎn)程服務(wù)的步驟:

  • 在服務(wù)的內(nèi)部創(chuàng)建一個(gè)內(nèi)部類,提供一個(gè)方法矫钓,可以間接調(diào)用服務(wù)的方法
  • 把暴露的接口文件的擴(kuò)展名改為.aidl文件 去掉訪問(wèn)修飾符
  • 實(shí)現(xiàn)服務(wù)的onbind方法浮禾,繼承Bander和實(shí)現(xiàn)aidl定義的接口,提供給外界可調(diào)用的方法
  • 在activity 中綁定服務(wù)份汗。bindService()
  • 在服務(wù)成功綁定的時(shí)候會(huì)回調(diào) onServiceConnected方法 傳遞一個(gè) IBinder對(duì)象
  • aidl定義的接口.Stub.asInterface(binder) 調(diào)用接口里面的方法

IntentService

IntentService是Service的子類盈电,比普通的Service增加了額外的功能。先看Service本身存在兩個(gè)問(wèn)題

  • Service不會(huì)專門啟動(dòng)一條單獨(dú)的進(jìn)程杯活,Service與它所在應(yīng)用位于同一個(gè)進(jìn)程中匆帚;
  • Service也不是專門一條新線程,因此不應(yīng)該在Service中直接處理耗時(shí)的任務(wù)旁钧;

IntentService特征:

  • 會(huì)創(chuàng)建獨(dú)立的worker線程來(lái)處理所有的Intent請(qǐng)求吸重;
  • 會(huì)創(chuàng)建獨(dú)立的worker線程來(lái)處理onHandleIntent()方法實(shí)現(xiàn)的代碼互拾,無(wú)需處理多線程問(wèn)題;
  • 所有請(qǐng)求處理完成后嚎幸,IntentService會(huì)自動(dòng)停止颜矿,無(wú)需調(diào)用stopSelf()方法停止Service;
  • 為Service的onBind()提供默認(rèn)實(shí)現(xiàn)嫉晶,返回null骑疆;
  • 為Service的onStartCommand提供默認(rèn)實(shí)現(xiàn),將請(qǐng)求Intent添加到隊(duì)列中替废;

Android四大組件 --- BroadcastReceiver

廣播被分為兩種不同的類型:“普通廣播(Normal broadcasts)”和“有序廣播(Ordered broadcasts)”箍铭。普通廣播是完全異步的,可以在同一時(shí)刻(邏輯上)被所有接收者接收到椎镣,消息傳遞的效率比較高诈火,但缺點(diǎn)是:接收者不能將處理結(jié)果傳遞給下一個(gè)接收者,并且無(wú)法終止廣播Intent的傳播状答;然而有序廣播是按照接收者聲明的優(yōu)先級(jí)別(聲明在intent-filter元素的android:priority屬性中冷守,數(shù)越大優(yōu)先級(jí)別越高,取值范圍:-1000到1000。也可以調(diào)用IntentFilter對(duì)象的setPriority()進(jìn)行設(shè)置)惊科,被接收者依次接收廣播拍摇。如:A的級(jí)別高于B,B的級(jí)別高于C,那么,廣播先傳給A译断,再傳給B授翻,最后傳給C。A得到廣播后孙咪,可以往廣播里存入數(shù)據(jù)堪唐,當(dāng)廣播傳給B時(shí),B可以從廣播中得到A存入的數(shù)據(jù)。
發(fā)送廣播

Context.sendBroadcast()
發(fā)送的是普通廣播翎蹈,所有訂閱者都有機(jī)會(huì)獲得并進(jìn)行處理淮菠。
Context.sendOrderedBroadcast()
發(fā)送的是有序廣播,系統(tǒng)會(huì)根據(jù)接收者聲明的優(yōu)先級(jí)別按順序逐個(gè)執(zhí)行接收者荤堪,前面的接收者有權(quán)終止廣播(BroadcastReceiver.abortBroadcast())合陵,
如果廣播被前面的接收者終止,后面的接收者就再也無(wú)法獲取到廣播澄阳。對(duì)于有序廣播拥知,前面的接收者可以將處理結(jié)果通過(guò)setResultExtras(Bundle)方法存放進(jìn)結(jié)果對(duì)象,
然后傳給下一個(gè)接收者,通過(guò)代碼:Bundle bundle =getResultExtras(true))可以獲取上一個(gè)接收者存入在結(jié)果對(duì)象中的數(shù)據(jù)。
系統(tǒng)收到短信袱蚓,發(fā)出的廣播屬于有序廣播版述。如果想阻止用戶收到短信襟齿,可以通過(guò)設(shè)置優(yōu)先級(jí)姻锁,
讓你們自定義的接收者先獲取到廣播,然后終止廣播猜欺,這樣用戶就接收不到短信了位隶。

生命周期:如果一個(gè)廣播處理完onReceive 那么系統(tǒng)將認(rèn)定此對(duì)象將不再是一個(gè)活動(dòng)的對(duì)象,也就會(huì)finished掉它开皿。
至此涧黄,大家應(yīng)該能明白 Android 的廣播生命周期的原理。

Paste_Image.png

步驟:
1副瀑,自定義一個(gè)類繼承BroadcastReceiver
2弓熏,重寫onReceive方法

3恋谭,在manifest.xml中注冊(cè)

注意BroadcastReceiver生命周期很短
如果需要在onReceiver完成一些耗時(shí)操作糠睡,應(yīng)該考慮在Service中開(kāi)啟一個(gè)新線程處理耗時(shí)操作,不應(yīng)該在BroadcastReceiver中開(kāi)啟一個(gè)新的線程疚颊,因?yàn)锽roadcastReceiver生命周期很短狈孔,在執(zhí)行完onReceiver以后就結(jié)束,如果開(kāi)啟一個(gè)新的線程材义,可能出現(xiàn)BroadcastRecevier退出以后線程還在均抽,而如果BroadcastReceiver所在的進(jìn)程結(jié)束了,該線程就會(huì)被標(biāo)記為一個(gè)空線程其掂,根據(jù)Android的內(nèi)存管理策略油挥,在系統(tǒng)內(nèi)存緊張的時(shí)候,會(huì)按照優(yōu)先級(jí)款熬,結(jié)束優(yōu)先級(jí)低的線程深寥,而空線程無(wú)異是優(yōu)先級(jí)最低的,這樣就可能導(dǎo)致BroadcastReceiver啟動(dòng)的子線程不能執(zhí)行完成贤牛。

示例

Paste_Image.png

注冊(cè)

Paste_Image.png

廣播還可以通過(guò)動(dòng)態(tài)注冊(cè):
registerReceiver(new MyBroadcastReceiver(),new IntentFilter("test"));

一定要加上這個(gè)權(quán)限(坑)
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>

注意:xml中注冊(cè)的優(yōu)先級(jí)高于動(dòng)態(tài)注冊(cè)廣播惋鹅。

發(fā)送廣播
Intent intent = new Intent("test"); sendBroadcast(intent);

靜態(tài)注冊(cè)和動(dòng)態(tài)注冊(cè)區(qū)別

  • 動(dòng)態(tài)注冊(cè)廣播不是常駐型廣播,也就是說(shuō)廣播跟隨activity的生命周期殉簸。注意: 在activity結(jié)束前闰集,移除廣播接收器。靜態(tài)注冊(cè)是常駐型般卑,也就是說(shuō)當(dāng)應(yīng)用程序關(guān)閉后武鲁,如果有信息廣播來(lái),程序也會(huì)被系統(tǒng)調(diào)用自動(dòng)運(yùn)行蝠检。
  • 當(dāng)廣播為有序廣播時(shí):
1 優(yōu)先級(jí)高的先接收 
2 同優(yōu)先級(jí)的廣播接收器沐鼠,動(dòng)態(tài)優(yōu)先于靜態(tài) 
3 同優(yōu)先級(jí)的同類廣播接收器,靜態(tài):先掃描的優(yōu)先于后掃描的蝇率,動(dòng)態(tài):先注冊(cè)的優(yōu)先于后注冊(cè)的迟杂。
  • 當(dāng)廣播為普通廣播時(shí):
1 無(wú)視優(yōu)先級(jí)刽沾,動(dòng)態(tài)廣播接收器優(yōu)先于靜態(tài)廣播接收器 
2 同優(yōu)先級(jí)的同類廣播接收器,靜態(tài):先掃描的優(yōu)先于后掃描的排拷,動(dòng)態(tài):先注冊(cè)的優(yōu)先于后注冊(cè)的侧漓。

小結(jié):

  • 在Android 中如果要發(fā)送一個(gè)廣播必須使用sendBroadCast 向系統(tǒng)發(fā)送對(duì)其感興趣的廣播接收器中。
  • 使用廣播必須要有一個(gè)intent 對(duì)象必設(shè)置其action動(dòng)作對(duì)象
  • 使用廣播必須在配置文件中顯式的指明該廣播對(duì)象
  • 每次接收廣播都會(huì)重新生成一個(gè)接收廣播的對(duì)象
  • 在BroadCastReceiver中盡量不要處理太多邏輯問(wèn)題监氢,建議復(fù)雜的邏輯交給Activity 或者 Service 去處理
  • 如果在AndroidManifest.xml中注冊(cè)布蔗,當(dāng)應(yīng)用程序關(guān)閉的時(shí)候,也會(huì)接收到廣播浪腐。在應(yīng)用程序中注冊(cè)就不產(chǎn)生這種情況了纵揍。

注意

當(dāng)如果要進(jìn)行的操作需要花費(fèi)比較長(zhǎng)的時(shí)間,則不適合放在BroadcastReceiver中進(jìn)行處理议街。
引用網(wǎng)上找到的一段解釋:
在 Android 中泽谨,程序的響應(yīng)( Responsive )被活動(dòng)管理器( Activity Manager )和窗口管理器( Window Manager )這兩個(gè)系統(tǒng)服務(wù)所監(jiān)視。當(dāng) BroadcastReceiver 在 10 秒內(nèi)沒(méi)有執(zhí)行完畢特漩,Android 會(huì)認(rèn)為該程序無(wú)響應(yīng)吧雹。所以在 BroadcastReceiver 里不能做一些比較耗時(shí)的操作,否側(cè)會(huì)彈出ANR ( Application No Response )的對(duì)話框涂身。如果需要完成一項(xiàng)比較耗時(shí)的工作雄卷,應(yīng)該通過(guò)發(fā)送Intent 給 Service ,由 Service 來(lái)完成蛤售。而不是使用子線程的方法來(lái)解決丁鹉,因?yàn)?BroadcastReceiver 的生命周期很短(在 onReceive() 執(zhí)行后 BroadcastReceiver 的實(shí)例就會(huì)被銷毀),子線程可能還沒(méi)有結(jié)束B(niǎo)roadcastReceiver 就先結(jié)束了悴能。如果 BroadcastReceiver 結(jié)束了揣钦,它的宿主進(jìn)程還在運(yùn)行,那么子線程還會(huì)繼續(xù)執(zhí)行搜骡。但宿主進(jìn)程此時(shí)很容易在系統(tǒng)需要內(nèi)存時(shí)被優(yōu)先殺死拂盯,因?yàn)樗鼘儆诳者M(jìn)程(沒(méi)有任何活動(dòng)組件的進(jìn)程)。

Android四大組件 --- ContentProvider

contentprovider是android四大組件之一的內(nèi)容提供器记靡,它主要的作用就是將程序的內(nèi)部的數(shù)據(jù)和外部進(jìn)行共享谈竿,為數(shù)據(jù)提供外部訪問(wèn)接口,被訪問(wèn)的數(shù)據(jù)主要以數(shù)據(jù)庫(kù)的形式存在摸吠,而且還可以選擇共享哪一部分的數(shù)據(jù)空凸。這樣一來(lái),對(duì)于程序當(dāng)中的隱私數(shù)據(jù)可以不共享寸痢,從而更加安全呀洲。contentprovider是android中一種跨程序共享數(shù)據(jù)的重要組件。

使用系統(tǒng)的ContentProvider

系統(tǒng)的ContentProvider有很多,如通話記錄道逗,短信兵罢,通訊錄等等,都需要和第三方的app進(jìn)行共享數(shù)據(jù)滓窍。既然是使用系統(tǒng)的卖词,那么contentprovider的具體實(shí)現(xiàn)就不需要我們擔(dān)心了,使用內(nèi)容提供者的步驟如下

  • 獲取ContentResolver實(shí)例
  • 確定Uri的內(nèi)容吏夯,并解析為具體的Uri實(shí)例
  • 通過(guò)ContentResolver實(shí)例來(lái)調(diào)用相應(yīng)的方法此蜈,傳遞相應(yīng)的參數(shù),但是第一個(gè)參數(shù)總是Uri噪生,它制定了我們要操作的數(shù)據(jù)的具體地址

可以通過(guò)讀取系統(tǒng)通訊錄的聯(lián)系人信息裆赵,顯示在Listview中來(lái)實(shí)踐這些知識(shí)。不要忘記在讀取通訊錄的時(shí)候跺嗽,在清單文件中要加入相應(yīng)的讀取權(quán)限战授。

自定義ContentProvider

系統(tǒng)的contentprovider在與我們交互的時(shí)候,只接受了一個(gè)Uri的參數(shù)抛蚁,然后根據(jù)我們的操作返回給我們結(jié)果陈醒。系統(tǒng)到底是如何根據(jù)一個(gè)Uri就能夠提供給我們準(zhǔn)確的結(jié)果呢惕橙?只有自己親自實(shí)現(xiàn)一個(gè)看看了瞧甩。

和之前提到的一樣,想重新自定義自己程序中的四大組件弥鹦,就必須重新實(shí)現(xiàn)一個(gè)類肚逸,重寫這個(gè)類中的抽象方法,在清單文件中注冊(cè)彬坏,最后才能夠正常使用朦促。

重新實(shí)現(xiàn)ContentProvider之后,發(fā)現(xiàn)我們重寫了6個(gè)重要的抽象方法

  • oncreate
  • query
  • update
  • insert
  • delete
  • gettype

大部分的方法在數(shù)據(jù)庫(kù)那里已經(jīng)見(jiàn)過(guò)了栓始,他們內(nèi)部的邏輯可想而知都是對(duì)數(shù)據(jù)的增刪改查操作务冕,其中這些方法的第一個(gè)參數(shù)大多都是Uri實(shí)例。其中有兩個(gè)方法比較特殊:

  • oncreate方法應(yīng)該是內(nèi)容提供者創(chuàng)建的時(shí)候所執(zhí)行的一個(gè)回調(diào)方法幻赚,負(fù)責(zé)數(shù)據(jù)庫(kù)的創(chuàng)建和更新操作禀忆。這個(gè)方法只有我們?cè)诔绦蛑蝎@取ContentResolver實(shí)例之后準(zhǔn)備訪問(wèn)共享數(shù)據(jù)的時(shí)候,才會(huì)被執(zhí)行落恼。
  • gettype方法是獲取我們通過(guò)參數(shù)傳遞進(jìn)去的Uri的MIME類型箩退,這個(gè)類型是什么,后面會(huì)有實(shí)例說(shuō)明佳谦。

內(nèi)容提供者首先要做的一個(gè)事情就是將我們傳遞過(guò)來(lái)的Uri解析出來(lái)戴涝,確定其他程序到底想訪問(wèn)哪些數(shù)據(jù)。Uri的形式一般有兩種:

1,以路徑名為結(jié)尾啥刻,這種Uri請(qǐng)求的是整個(gè)表的數(shù)據(jù)奸鸯,如: content://com.demo.androiddemo.provider/tabl1 標(biāo)識(shí)我們要訪問(wèn)tabl1表中所有的數(shù)據(jù)

2,以id列值結(jié)尾可帽,這種Uri請(qǐng)求的是該表中和其提供的列值相等的單條數(shù)據(jù)府喳。 content://com.demo.androiddemo.provider/tabl1/1 標(biāo)識(shí)我們要訪問(wèn)tabl1表中_id列值為1的數(shù)據(jù)。

如果是內(nèi)容提供器的設(shè)計(jì)者蘑拯,那么我們肯定知道這個(gè)程序的數(shù)據(jù)庫(kù)是什么樣的钝满,每一張表,或者每一張表中的_id都應(yīng)該有一個(gè)唯一的內(nèi)容Uri申窘。我們可以將傳遞進(jìn)來(lái)的Uri和我們存好的Uri進(jìn)行匹配弯蚜,匹配到了之后,就說(shuō)明數(shù)據(jù)源已經(jīng)找到剃法,便可以進(jìn)行相應(yīng)的增刪改查操作碎捺。

ContentProvider詳解

五種布局

RelativeLayout 實(shí)現(xiàn)平分父布局

Paste_Image.png

RelativeLayout 的子view的 layout_gravity屬性是沒(méi)有效果的,而是通過(guò)

Paste_Image.png

這樣的一些屬性來(lái)代替贷洲。

文/Lemon_95(簡(jiǎn)書(shū)作者)
原文鏈接:http://www.reibang.com/p/51aaa65d5d25
著作權(quán)歸作者所有收厨,轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),并標(biāo)注“簡(jiǎn)書(shū)作者”优构。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末诵叁,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子钦椭,更是在濱河造成了極大的恐慌拧额,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,816評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件彪腔,死亡現(xiàn)場(chǎng)離奇詭異侥锦,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)德挣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門恭垦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人格嗅,你說(shuō)我怎么就攤上這事番挺。” “怎么了吗浩?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,300評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵建芙,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我懂扼,道長(zhǎng)禁荸,這世上最難降的妖魔是什么右蒲? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,780評(píng)論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮赶熟,結(jié)果婚禮上瑰妄,老公的妹妹穿的比我還像新娘。我一直安慰自己映砖,他們只是感情好间坐,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,890評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著邑退,像睡著了一般竹宋。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上地技,一...
    開(kāi)封第一講書(shū)人閱讀 50,084評(píng)論 1 291
  • 那天蜈七,我揣著相機(jī)與錄音,去河邊找鬼莫矗。 笑死飒硅,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的作谚。 我是一名探鬼主播三娩,決...
    沈念sama閱讀 39,151評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼妹懒!你這毒婦竟也來(lái)了雀监?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,912評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤彬伦,失蹤者是張志新(化名)和其女友劉穎滔悉,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體单绑,經(jīng)...
    沈念sama閱讀 44,355評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,666評(píng)論 2 327
  • 正文 我和宋清朗相戀三年曹宴,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了搂橙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,809評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡笛坦,死狀恐怖区转,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情版扩,我是刑警寧澤废离,帶...
    沈念sama閱讀 34,504評(píng)論 4 334
  • 正文 年R本政府宣布,位于F島的核電站礁芦,受9級(jí)特大地震影響蜻韭,放射性物質(zhì)發(fā)生泄漏悼尾。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,150評(píng)論 3 317
  • 文/蒙蒙 一肖方、第九天 我趴在偏房一處隱蔽的房頂上張望闺魏。 院中可真熱鬧,春花似錦俯画、人聲如沸析桥。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)泡仗。三九已至,卻和暖如春猜憎,著一層夾襖步出監(jiān)牢的瞬間沮焕,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,121評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工拉宗, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留峦树,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,628評(píng)論 2 362
  • 正文 我出身青樓旦事,卻偏偏與公主長(zhǎng)得像魁巩,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子姐浮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,724評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容