Android四大組件用了很多遍了污桦,但還是有很多細(xì)節(jié)容易忘記丰涉,所以就寫下來吧!
Activity
Activity的生命周期
Activity的簡單生命周期流程為onCreate();→onStart();【注:此時(shí)Activity處于不可見狀態(tài)】→onResume();【注:此時(shí)Activity處于運(yùn)行狀態(tài)】→onPause();【注:此時(shí)Activity處于暫停狀態(tài)】→onStop();【注:此時(shí)Activity處于停滯狀態(tài)】→onDestroy();【注:調(diào)用了此方法后Activity生命周期結(jié)束】
其中當(dāng)Activity正在重新啟動(dòng)的時(shí)候繁调,從不可見變?yōu)榭梢姷臅r(shí)候舅桩,會(huì)調(diào)用到onRestart();也就是說一個(gè)Activity包含七個(gè)生命周期流程
- Activity被其他Activity覆蓋其上,系統(tǒng)會(huì)調(diào)用onPause()方法寨蹋,暫停當(dāng)前Activity的執(zhí)行松蒜,若用戶取消了覆蓋,系統(tǒng)會(huì)調(diào)用onResume()方法已旧,重新進(jìn)入到運(yùn)行狀態(tài)秸苗。
- Activity跳轉(zhuǎn)到了新的Activity界面或者被后臺了或者鎖屏?xí)r,系統(tǒng)會(huì)調(diào)用onPause();然后調(diào)用onStop();使Activity進(jìn)入到停滯狀態(tài)运褪,如果重新回到了該Activity界面(上一個(gè)Activity或者從后臺變?yōu)榱饲芭_時(shí)或者解開鎖屏?xí)r)惊楼,系統(tǒng)會(huì)調(diào)用onRestart();再調(diào)用onStart();最后調(diào)用onResume()方法使該Activity進(jìn)入到運(yùn)行狀態(tài)
- 當(dāng)用戶退出Activity時(shí)會(huì)調(diào)用onPause();然后調(diào)用onStop();最后調(diào)用onDestory();結(jié)束Activity生命周期
- 當(dāng)Activity中彈出dialog對話框的時(shí)候,Activity不會(huì)調(diào)用onPause();只有當(dāng)Activity啟動(dòng)了dialog風(fēng)格的Activity時(shí)才會(huì)調(diào)用
- 當(dāng)Activity是由于異常情況下終止的秸讹,系統(tǒng)會(huì)調(diào)用onSaveInstance來保存當(dāng)前Activity狀態(tài)檀咙,這個(gè)方法調(diào)用的時(shí)機(jī)是在onStop之前的,當(dāng)Activity重新創(chuàng)建后璃诀,系統(tǒng)會(huì)調(diào)用onRestoreInstanceState,并且把Activity銷毀時(shí)的onSaveInstanceState方法保存的bundle對象作為參數(shù)同時(shí)傳遞給onRestoreInstanceState和onCreate方法
Activity的四種啟動(dòng)模式
Activity有四種啟動(dòng)模式 standard,singleTop,singleTask,singleInstance弧可,這四種模式我們可以在清單文件的<Activity節(jié)點(diǎn)下通過android:launchMode來進(jìn)行配置
- standard模式:在這種模式下,activity默認(rèn)會(huì)進(jìn)入啟動(dòng)它的activity所屬的任務(wù)棧中劣欢。這也是默認(rèn)的一種模式
- singleTop模式:棧頂復(fù)用模式。如果新activity位于任務(wù)棧的棧頂?shù)臅r(shí)候涣楷,activity不會(huì)被重新創(chuàng)建扰付,同時(shí)它的onNewIntent方法會(huì)被回調(diào)。
- singleTask模式:棧內(nèi)復(fù)用模式价脾。只要activity在一個(gè)棧中存在,那么多次啟動(dòng)此activity不會(huì)被重新創(chuàng)建單例搔确,系統(tǒng)會(huì)回調(diào)onNewIntent彼棍。這種模式可以稱為單例模式,只會(huì)存在一種膳算,有則直接從棧中調(diào)用座硕,沒有則創(chuàng)建并且壓入棧中
- singleInstance模式:單實(shí)例模式。這種模式的activity只能單獨(dú)地位于一個(gè)任務(wù)棧中涕蜂,這種與singleTask有點(diǎn)類似华匾,其實(shí)也是有則直接調(diào)用,沒有則創(chuàng)建并且放入棧中机隙,只不過singleTask是可以和其他的Activity放在同一個(gè)棧中蜘拉,singleInstance則是只會(huì)將創(chuàng)建的Activity放在一個(gè)棧中,并且這個(gè)棧中只會(huì)有這一個(gè)Activity實(shí)例
Service
Service分為兩種有鹿,一種是Service(這一種是運(yùn)行在主線程中的旭旭,如果要執(zhí)行耗時(shí)操作,可在service中創(chuàng)建一個(gè)異步來執(zhí)行)葱跋,一種是IntentService(這是一種異步服務(wù)持寄,是繼承于Service的子類),所以推薦當(dāng)要執(zhí)行耗時(shí)操作時(shí)使用IntentService娱俺,如果不耗時(shí)稍味,我們可以使用Service
Service
Service的兩種啟動(dòng)方式
- 通過start方法開啟服務(wù)
- 創(chuàng)建一個(gè)類繼承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");
}
}
- 在清單文件中注冊這個(gè)服務(wù)
<service
android:name=".MyService"
android:enabled="true"
android:exported="true"></service>
- 通過startService方法啟動(dòng)服務(wù)
Intent intent = new Intent(this, MyService.class);
startService(intent);
- 當(dāng)不用服務(wù)的時(shí)候通過stopService()方法停止該服務(wù)
stopService(intent);
特點(diǎn): 通過start方法啟動(dòng)的service一旦服務(wù)開啟就跟調(diào)用者(開啟者)沒有任何關(guān)系了。開啟者退出了荠卷,開啟者掛了模庐,服務(wù)還在后臺長期的運(yùn)行,開啟者不能調(diào)用服務(wù)里面的方法油宜。
- 通過bind的方式啟動(dòng)服務(wù)
- 創(chuàng)建一個(gè)類繼承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");
}
}
- 在清單文件中注冊這個(gè)服務(wù)
<service
android:name=".MyService"
android:enabled="true"
android:exported="true"></service>
- 通過bindService方法啟動(dòng)服務(wù)
Intent intent = new Intent(this, MyService.class);
bindService(Intent,ServiceConnection,int);
- 當(dāng)不用服務(wù)的時(shí)候通過unbindService()方法停止該服務(wù)
unbindService(ServiceConnection);
特點(diǎn):使用bind方法啟動(dòng)的服務(wù)掂碱,則調(diào)用者掛了,服務(wù)也掛了验庙,調(diào)用者可以調(diào)用服務(wù)中的方法
遠(yuǎn)程服務(wù)
調(diào)用者與Service不在同一個(gè)進(jìn)程顶吮,這是一種跨進(jìn)程通信的方式Android綁定遠(yuǎn)程服務(wù)
步驟:
- 在服務(wù)的內(nèi)部創(chuàng)建一個(gè)內(nèi)部類,提供一個(gè)方法粪薛,可以間接調(diào)用服務(wù)的方法
- 把暴露的接口文件的擴(kuò)展名改為.aidl文件 去掉訪問修飾符
- 實(shí)現(xiàn)服務(wù)的onbind方法悴了,繼承Bander和實(shí)現(xiàn)aidl定義的接口,提供給外界可調(diào)用的方法
- 在activity 中綁定服務(wù)。bindService()
- 在服務(wù)成功綁定的時(shí)候會(huì)回調(diào) onServiceConnected方法 傳遞一個(gè) IBinder對象
- aidl定義的接口.Stub.asInterface(binder) 調(diào)用接口里面的方法
IntentService
這個(gè)Service在上面也說過湃交,是一個(gè)異步服務(wù)
IntentService特征:
- 會(huì)創(chuàng)建獨(dú)立的worker線程來處理所有的Intent請求熟空;
- 會(huì)創(chuàng)建獨(dú)立的worker線程來處理onHandleIntent()方法實(shí)現(xiàn)的代碼,無需處理多線程問題搞莺;
- 所有請求處理完成后息罗,IntentService會(huì)自動(dòng)停止,無需調(diào)用stopSelf()方法停止Service才沧;
- 為Service的onBind()提供默認(rèn)實(shí)現(xiàn)迈喉,返回null;
- 為Service的onStartCommand提供默認(rèn)實(shí)現(xiàn)温圆,將請求Intent添加到隊(duì)列中挨摸;
BroadcastReceiver
廣播分為兩種,一種是普通廣播岁歉,或者稱為無序廣播得运,另一種是有序廣播
無序廣播與有序廣播
無序廣播是完全異步的,在同一時(shí)刻在邏輯上是能夠被所有的接收者接收到的锅移,傳遞的效率高熔掺,缺點(diǎn)是接收者不能處理結(jié)果傳給下個(gè)接收者,并且無法終止廣播的傳播(其實(shí)有序廣播就是和這個(gè)相反的非剃,有順序的傳播置逻,兩個(gè)廣播的定義就是完全相反的,這個(gè)比較好記)
Context.sendBroadcast()
發(fā)送的是普通廣播备绽,所有訂閱者都有機(jī)會(huì)獲得并進(jìn)行處理诽偷。
廣播的生命周期就是在處理完onReceive時(shí),系統(tǒng)將認(rèn)定他不是一個(gè)活動(dòng)的對象了疯坤,就是殺掉他,由于廣播的生命周期很短深浮,所以不建議在onReceive中執(zhí)行一些耗時(shí)操作
創(chuàng)建一個(gè)廣播的步驟:
- 創(chuàng)建一個(gè)類繼承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"/>//這里自定義一個(gè)廣播動(dòng)作
</intent-filter>
</receiver>
或者動(dòng)態(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)注冊和動(dòng)態(tài)注冊區(qū)別
動(dòng)態(tài)注冊廣播不是常駐型廣播,也就是說廣播跟隨activity的生命周期飞苇。注意: 在activity結(jié)束前菌瘫,移除廣播接收器。
靜態(tài)注冊是常駐型布卡,也就是說當(dāng)應(yīng)用程序關(guān)閉后雨让,如果有信息廣播來,程序也會(huì)被系統(tǒng)調(diào)用自動(dòng)運(yùn)行忿等。
- 當(dāng)廣播為有序廣播時(shí):
- 優(yōu)先級高的先接收
- 同優(yōu)先級的廣播接收器栖忠,動(dòng)態(tài)優(yōu)先于靜態(tài)
- 同優(yōu)先級的同類廣播接收器,靜態(tài):先掃描的優(yōu)先于后掃描的,動(dòng)態(tài):先注冊的優(yōu)先于后注冊的庵寞。
- 當(dāng)廣播為普通廣播時(shí):
- 無視優(yōu)先級狸相,動(dòng)態(tài)廣播接收器優(yōu)先于靜態(tài)廣播接收器
- 同優(yōu)先級的同類廣播接收器,靜態(tài):先掃描的優(yōu)先于后掃描的捐川,動(dòng)態(tài):先注冊的優(yōu)先于后注冊的脓鹃。
Service小結(jié):
- 在Android 中如果要發(fā)送一個(gè)廣播必須使用sendBroadCast 向系統(tǒng)發(fā)送對其感興趣的廣播接收器中。
- 使用廣播必須要有一個(gè)intent 對象必設(shè)置其action動(dòng)作對象
- 使用廣播必須在配置文件中顯式的指明該廣播對象
- 每次接收廣播都會(huì)重新生成一個(gè)接收廣播的對象
- 在BroadCastReceiver中盡量不要處理太多邏輯問題古沥,建議復(fù)雜的邏輯交給Activity 或者 Service 去處理
- 如果在AndroidManifest.xml中注冊瘸右,當(dāng)應(yīng)用程序關(guān)閉的時(shí)候,也會(huì)接收到廣播岩齿。在應(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
學(xué)習(xí)鏈接:內(nèi)容提供者(ContentProvider)