你不知道Android四大組件秘密

Android四大組件用了很多遍了听诸,但還是有很多細(xì)節(jié)容易忘記,所以就寫下來吧潮瓶!

Activity

Activity的生命周期

?

在這里插入圖片描述

Activity的簡單生命周期流程為onCreate();→onStart();【注:此時Activity處于不可見狀態(tài)】→onResume();【注:此時Activity處于運(yùn)行狀態(tài)】→onPause();【注:此時Activity處于暫停狀態(tài)】→onStop();【注:此時Activity處于停滯狀態(tài)】→onDestroy();【注:調(diào)用了此方法后Activity生命周期結(jié)束】
其中當(dāng)Activity正在重新啟動的時候陶冷,從不可見變?yōu)榭梢姷臅r候,會調(diào)用到onRestart();也就是說一個Activity包含七個生命周期流程

  • Activity被其他Activity覆蓋其上毯辅,系統(tǒng)會調(diào)用onPause()方法埂伦,暫停當(dāng)前Activity的執(zhí)行,若用戶取消了覆蓋悉罕,系統(tǒng)會調(diào)用onResume()方法赤屋,重新進(jìn)入到運(yùn)行狀態(tài)。
  • Activity跳轉(zhuǎn)到了新的Activity界面或者被后臺了或者鎖屏?xí)r壁袄,系統(tǒng)會調(diào)用onPause();然后調(diào)用onStop();使Activity進(jìn)入到停滯狀態(tài)类早,如果重新回到了該Activity界面(上一個Activity或者從后臺變?yōu)榱饲芭_時或者解開鎖屏?xí)r),系統(tǒng)會調(diào)用onRestart();再調(diào)用onStart();最后調(diào)用onResume()方法使該Activity進(jìn)入到運(yùn)行狀態(tài)
  • 當(dāng)用戶退出Activity時會調(diào)用onPause();然后調(diào)用onStop();最后調(diào)用onDestory();結(jié)束Activity生命周期
  • 當(dāng)Activity中彈出dialog對話框的時候嗜逻,Activity不會調(diào)用onPause();只有當(dāng)Activity啟動了dialog風(fēng)格的Activity時才會調(diào)用
  • 當(dāng)Activity是由于異常情況下終止的涩僻,系統(tǒng)會調(diào)用onSaveInstance來保存當(dāng)前Activity狀態(tài),這個方法調(diào)用的時機(jī)是在onStop之前的栈顷,當(dāng)Activity重新創(chuàng)建后逆日,系統(tǒng)會調(diào)用onRestoreInstanceState,并且把Activity銷毀時的onSaveInstanceState方法保存的bundle對象作為參數(shù)同時傳遞給onRestoreInstanceState和onCreate方法

Activity的四種啟動模式

Activity有四種啟動模式 standard,singleTop,singleTask,singleInstance,這四種模式我們可以在清單文件的<Activity節(jié)點(diǎn)下通過android:launchMode來進(jìn)行配置

  • standard模式:在這種模式下萄凤,activity默認(rèn)會進(jìn)入啟動它的activity所屬的任務(wù)棧中室抽。這也是默認(rèn)的一種模式
  • singleTop模式:棧頂復(fù)用模式。如果新activity位于任務(wù)棧的棧頂?shù)臅r候靡努,activity不會被重新創(chuàng)建坪圾,同時它的onNewIntent方法會被回調(diào)。
  • singleTask模式:棧內(nèi)復(fù)用模式惑朦。只要activity在一個棧中存在兽泄,那么多次啟動此activity不會被重新創(chuàng)建單例,系統(tǒng)會回調(diào)onNewIntent漾月。這種模式可以稱為單例模式病梢,只會存在一種,有則直接從棧中調(diào)用梁肿,沒有則創(chuàng)建并且壓入棧中
  • singleInstance模式:單實(shí)例模式蜓陌。這種模式的activity只能單獨(dú)地位于一個任務(wù)棧中觅彰,這種與singleTask有點(diǎn)類似,其實(shí)也是有則直接調(diào)用护奈,沒有則創(chuàng)建并且放入棧中缔莲,只不過singleTask是可以和其他的Activity放在同一個棧中,singleInstance則是只會將創(chuàng)建的Activity放在一個棧中霉旗,并且這個棧中只會有這一個Activity實(shí)例

Service

Service分為兩種痴奏,一種是Service(這一種是運(yùn)行在主線程中的,如果要執(zhí)行耗時操作厌秒,可在service中創(chuàng)建一個異步來執(zhí)行)读拆,一種是IntentService(這是一種異步服務(wù),是繼承于Service的子類)鸵闪,所以推薦當(dāng)要執(zhí)行耗時操作時使用IntentService檐晕,如果不耗時,我們可以使用Service

Service

Service的兩種啟動方式

  1. 通過start方法開啟服務(wù)
  • 創(chuàng)建一個類繼承Service
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

public class MyService extends Service {
    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }
}
  • 在清單文件中注冊這個服務(wù)
   <service
            android:name=".MyService"
            android:enabled="true"
            android:exported="true"></service>
  • 通過startService方法啟動服務(wù)
   Intent intent = new Intent(this, MyService.class);
   startService(intent);
  • 當(dāng)不用服務(wù)的時候通過stopService()方法停止該服務(wù)
stopService(intent);

特點(diǎn): 通過start方法啟動的service一旦服務(wù)開啟就跟調(diào)用者(開啟者)沒有任何關(guān)系了蚌讼。開啟者退出了辟灰,開啟者掛了,服務(wù)還在后臺長期的運(yùn)行篡石,開啟者不能調(diào)用服務(wù)里面的方法芥喇。

  1. 通過bind的方式啟動服務(wù)
  • 創(chuàng)建一個類繼承Service
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

public class MyService extends Service {
    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }
}
  • 在清單文件中注冊這個服務(wù)
   <service
            android:name=".MyService"
            android:enabled="true"
            android:exported="true"></service>
  • 通過startService方法啟動服務(wù)
   Intent intent = new Intent(this, MyService.class);
   bindService(Intent,ServiceConnection,int);
  • 當(dāng)不用服務(wù)的時候通過stopService()方法停止該服務(wù)
unbindService(ServiceConnection);

特點(diǎn):使用bind方法啟動的服務(wù),則調(diào)用者掛了继控,服務(wù)也掛了,調(diào)用者可以調(diào)用服務(wù)中的方法

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

調(diào)用者與Service不在同一個進(jìn)程冶忱,這是一種跨進(jìn)程通信的方式Android綁定遠(yuǎn)程服務(wù)

步驟:

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

IntentService

這個Service在上面也說過底哥,是一個異步服務(wù)
IntentService特征:

  • 會創(chuàng)建獨(dú)立的worker線程來處理所有的Intent請求朗恳;
  • 會創(chuàng)建獨(dú)立的worker線程來處理onHandleIntent()方法實(shí)現(xiàn)的代碼臀脏,無需處理多線程問題;
  • 所有請求處理完成后,IntentService會自動停止佣盒,無需調(diào)用stopSelf()方法停止Service全景;
  • 為Service的onBind()提供默認(rèn)實(shí)現(xiàn),返回null钥弯;
  • 為Service的onStartCommand提供默認(rèn)實(shí)現(xiàn)睛蛛,將請求Intent添加到隊(duì)列中和悦;

BroadcastReceiver

廣播分為兩種吵血,一種是普通廣播蹋辅,或者稱為無序廣播,另一種是有序廣播

無序廣播與有序廣播

無序廣播是完全異步的挫掏,在同一時刻在邏輯上是能夠被所有的接收者接收到的侦另,傳遞的效率高,缺點(diǎn)是接收者不能處理結(jié)果傳給下個接收者尉共,并且無法終止廣播的傳播(其實(shí)有序廣播就是和這個相反的褒傅,有順序的傳播,兩個廣播的定義就是完全相反的袄友,這個比較好記)

Context.sendBroadcast()
發(fā)送的是普通廣播殿托,所有訂閱者都有機(jī)會獲得并進(jìn)行處理。

廣播的生命周期就是在處理完onReceive時剧蚣,系統(tǒng)將認(rèn)定他不是一個活動的對象了支竹,就是殺掉他,由于廣播的生命周期很短鸠按,所以不建議在onReceive中執(zhí)行一些耗時操作

創(chuàng)建一個廣播的步驟:

  • 創(chuàng)建一個類繼承BroadcastReceiver礼搁,并且重寫其onReceive方法
public class MyBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i("fuck","intent-action : " + intent.getAction());
        if(intent.getAction().equals("test")){
            Toast.makeText(context,"fuck",Toast.LENGTH_LONG).show();
        }
    }

}
  • 在清單文件中注冊(靜態(tài)注冊)
     //廣播接收器
        <receiver android:name=".broadcast.MyBroadcastReceiver">

            <intent-filter>
                <action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
                <action android:name="test"/>//這里自定義一個廣播動作
            </intent-filter>

        </receiver>

或者動態(tài)注冊

registerReceiver(new MyBroadcastReceiver(),new IntentFilter("test"));

  • 加上權(quán)限
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>

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

靜態(tài)注冊和動態(tài)注冊區(qū)別

動態(tài)注冊廣播不是常駐型廣播惫谤,也就是說廣播跟隨activity的生命周期摇邦。注意: 在activity結(jié)束前蛉拙,移除廣播接收器如庭。
靜態(tài)注冊是常駐型出吹,也就是說當(dāng)應(yīng)用程序關(guān)閉后跌榔,如果有信息廣播來折剃,程序也會被系統(tǒng)調(diào)用自動運(yùn)行镶奉。

  • 當(dāng)廣播為有序廣播時:
  1. 優(yōu)先級高的先接收
  2. 同優(yōu)先級的廣播接收器测蹲,動態(tài)優(yōu)先于靜態(tài)
  3. 同優(yōu)先級的同類廣播接收器莹捡,靜態(tài):先掃描的優(yōu)先于后掃描的,動態(tài):先注冊的優(yōu)先于后注冊的扣甲。
  • 當(dāng)廣播為普通廣播時:
  1. 無視優(yōu)先級篮赢,動態(tài)廣播接收器優(yōu)先于靜態(tài)廣播接收器
  2. 同優(yōu)先級的同類廣播接收器齿椅,靜態(tài):先掃描的優(yōu)先于后掃描的,動態(tài):先注冊的優(yōu)先于后注冊的启泣。

Service小結(jié):

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

ContentProvider

contentprovider是android四大組件之一的內(nèi)容提供器芭梯,它主要的作用就是將程序的內(nèi)部的數(shù)據(jù)和外部進(jìn)行共享,為數(shù)據(jù)提供外部訪問接口弄喘,被訪問的數(shù)據(jù)主要以數(shù)據(jù)庫的形式存在玖喘,而且還可以選擇共享哪一部分的數(shù)據(jù)。這樣一來蘑志,對于程序當(dāng)中的隱私數(shù)據(jù)可以不共享累奈,從而更加安全。contentprovider是android中一種跨程序共享數(shù)據(jù)的重要組件急但。
自定義的內(nèi)容提供者沒用過费尽,因?yàn)闆]有實(shí)際的業(yè)務(wù)需求,系統(tǒng)的內(nèi)容提供者用的比較多羊始,所以具體也不知道該如何記錄ContentProvider
<meta charset="utf-8">

最后

一點(diǎn)題外話:

最近面試被懟了旱幼?缺面試題刷提升自己嗎?

點(diǎn)擊:

Android學(xué)習(xí)PDF+架構(gòu)視頻+面試文檔+源碼筆記

來獲取學(xué)習(xí)資料提升自己去挑戰(zhàn)一下BAT面試難關(guān)吧

當(dāng)程序員容易突委,當(dāng)一個優(yōu)秀的程序員是需要不斷學(xué)習(xí)的柏卤,從初級程序員到高級程序員,從初級架構(gòu)師到資深架構(gòu)師匀油,或者走向管理缘缚,從技術(shù)經(jīng)理到技術(shù)總監(jiān),每個階段都需要掌握不同的能力敌蚜。早早確定自己的職業(yè)方向桥滨,才能在工作和能力提升中甩開同齡人。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末弛车,一起剝皮案震驚了整個濱河市齐媒,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌纷跛,老刑警劉巖喻括,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異贫奠,居然都是意外死亡唬血,警方通過查閱死者的電腦和手機(jī)望蜡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拷恨,“玉大人脖律,你說我怎么就攤上這事⊥笾叮” “怎么了小泉?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長兜挨。 經(jīng)常有香客問我,道長眯分,這世上最難降的妖魔是什么拌汇? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮弊决,結(jié)果婚禮上噪舀,老公的妹妹穿的比我還像新娘。我一直安慰自己飘诗,他們只是感情好与倡,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著昆稿,像睡著了一般纺座。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上溉潭,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天净响,我揣著相機(jī)與錄音,去河邊找鬼喳瓣。 笑死馋贤,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的畏陕。 我是一名探鬼主播配乓,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼惠毁!你這毒婦竟也來了犹芹?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤鞠绰,失蹤者是張志新(化名)和其女友劉穎羽莺,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體洞豁,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡盐固,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年荒给,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片刁卜。...
    茶點(diǎn)故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡志电,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蛔趴,到底是詐尸還是另有隱情挑辆,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布孝情,位于F島的核電站鱼蝉,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏箫荡。R本人自食惡果不足惜魁亦,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望羔挡。 院中可真熱鬧洁奈,春花似錦、人聲如沸绞灼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽低矮。三九已至印叁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間军掂,已是汗流浹背喉钢。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留良姆,地道東北人肠虽。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像玛追,于是被迫代替她去往敵國和親税课。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評論 2 345