Android四大組件用了很多遍了,但還是有很多細節容易忘記,所以就寫下來吧!
Activity
Activity的生命週期
在這裏插入圖片描述
Activity的簡單生命週期流程爲onCreate();→onStart();【注:此時Activity處於不可見狀態】→onResume();【注:此時Activity處於運行狀態】→onPause();【注:此時Activity處於暫停狀態】→onStop();【注:此時Activity處於停滯狀態】→onDestroy();【注:調用了此方法後Activity生命週期結束】
其中當Activity正在重新啓動的時候,從不可見變爲可見的時候,會調用到onRestart();也就是說一個Activity包含七個生命週期流程
- Activity被其他Activity覆蓋其上,系統會調用onPause()方法,暫停當前Activity的執行,若用戶取消了覆蓋,系統會調用onResume()方法,重新進入到運行狀態。
- Activity跳轉到了新的Activity界面或者被後臺了或者鎖屏時,系統會調用onPause();然後調用onStop();使Activity進入到停滯狀態,如果重新回到了該Activity界面(上一個Activity或者從後臺變爲了前臺時或者解開鎖屏時),系統會調用onRestart();再調用onStart();最後調用onResume()方法使該Activity進入到運行狀態
- 當用戶退出Activity時會調用onPause();然後調用onStop();最後調用onDestory();結束Activity生命週期
- 當Activity中彈出dialog對話框的時候,Activity不會調用onPause();只有當Activity啓動了dialog風格的Activity時纔會調用
- 當Activity是由於異常情況下終止的,系統會調用onSaveInstance來保存當前Activity狀態,這個方法調用的時機是在onStop之前的,當Activity重新創建後,系統會調用onRestoreInstanceState,並且把Activity銷燬時的onSaveInstanceState方法保存的bundle對象作爲參數同時傳遞給onRestoreInstanceState和onCreate方法
Activity的四種啓動模式
Activity有四種啓動模式 standard,singleTop,singleTask,singleInstance,這四種模式我們可以在清單文件的<Activity節點下通過android:launchMode來進行配置
- standard模式:在這種模式下,activity默認會進入啓動它的activity所屬的任務棧中。這也是默認的一種模式
- singleTop模式:棧頂複用模式。如果新activity位於任務棧的棧頂的時候,activity不會被重新創建,同時它的onNewIntent方法會被回調。
- singleTask模式:棧內複用模式。只要activity在一個棧中存在,那麼多次啓動此activity不會被重新創建單例,系統會回調onNewIntent。這種模式可以稱爲單例模式,只會存在一種,有則直接從棧中調用,沒有則創建並且壓入棧中
- singleInstance模式:單實例模式。這種模式的activity只能單獨地位於一個任務棧中,這種與singleTask有點類似,其實也是有則直接調用,沒有則創建並且放入棧中,只不過singleTask是可以和其他的Activity放在同一個棧中,singleInstance則是隻會將創建的Activity放在一個棧中,並且這個棧中只會有這一個Activity實例
Service
Service分爲兩種,一種是Service(這一種是運行在主線程中的,如果要執行耗時操作,可在service中創建一個異步來執行),一種是IntentService(這是一種異步服務,是繼承於Service的子類),所以推薦當要執行耗時操作時使用IntentService,如果不耗時,我們可以使用Service
Service
Service的兩種啓動方式
- 通過start方法開啓服務
- 創建一個類繼承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");
}
}
- 在清單文件中註冊這個服務
<service
android:name=".MyService"
android:enabled="true"
android:exported="true"></service>
- 通過startService方法啓動服務
Intent intent = new Intent(this, MyService.class);
startService(intent);
- 當不用服務的時候通過stopService()方法停止該服務
stopService(intent);
特點: 通過start方法啓動的service一旦服務開啓就跟調用者(開啓者)沒有任何關係了。開啓者退出了,開啓者掛了,服務還在後臺長期的運行,開啓者不能調用服務裏面的方法。
- 通過bind的方式啓動服務
- 創建一個類繼承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");
}
}
- 在清單文件中註冊這個服務
<service
android:name=".MyService"
android:enabled="true"
android:exported="true"></service>
- 通過startService方法啓動服務
Intent intent = new Intent(this, MyService.class);
bindService(Intent,ServiceConnection,int);
- 當不用服務的時候通過stopService()方法停止該服務
unbindService(ServiceConnection);
特點:使用bind方法啓動的服務,則調用者掛了,服務也掛了,調用者可以調用服務中的方法
遠程服務
調用者與Service不在同一個進程,這是一種跨進程通信的方式Android綁定遠程服務
步驟:
- 在服務的內部創建一個內部類,提供一個方法,可以間接調用服務的方法
- 把暴露的接口文件的擴展名改爲.aidl文件 去掉訪問修飾符
- 實現服務的onbind方法,繼承Bander和實現aidl定義的接口,提供給外界可調用的方法
- 在activity 中綁定服務。bindService()
- 在服務成功綁定的時候會回調 onServiceConnected方法 傳遞一個 IBinder對象
- aidl定義的接口.Stub.asInterface(binder) 調用接口裏面的方法
IntentService
這個Service在上面也說過,是一個異步服務
IntentService特徵:
- 會創建獨立的worker線程來處理所有的Intent請求;
- 會創建獨立的worker線程來處理onHandleIntent()方法實現的代碼,無需處理多線程問題;
- 所有請求處理完成後,IntentService會自動停止,無需調用stopSelf()方法停止Service;
- 爲Service的onBind()提供默認實現,返回null;
- 爲Service的onStartCommand提供默認實現,將請求Intent添加到隊列中;
BroadcastReceiver
廣播分爲兩種,一種是普通廣播,或者稱爲無序廣播,另一種是有序廣播
無序廣播與有序廣播
無序廣播是完全異步的,在同一時刻在邏輯上是能夠被所有的接收者接收到的,傳遞的效率高,缺點是接收者不能處理結果傳給下個接收者,並且無法終止廣播的傳播(其實有序廣播就是和這個相反的,有順序的傳播,兩個廣播的定義就是完全相反的,這個比較好記)
Context.sendBroadcast()
發送的是普通廣播,所有訂閱者都有機會獲得並進行處理。
廣播的生命週期就是在處理完onReceive時,系統將認定他不是一個活動的對象了,就是殺掉他,由於廣播的生命週期很短,所以不建議在onReceive中執行一些耗時操作
創建一個廣播的步驟:
- 創建一個類繼承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();
}
}
}
- 在清單文件中註冊(靜態註冊)
//廣播接收器
<receiver android:name=".broadcast.MyBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
<action android:name="test"/>//這裏自定義一個廣播動作
</intent-filter>
</receiver>
或者動態註冊
registerReceiver(new MyBroadcastReceiver(),new IntentFilter("test"));
加上權限
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
- 發送廣播
Intent intent = new Intent("test");
sendBroadcast(intent);
靜態註冊和動態註冊區別
動態註冊廣播不是常駐型廣播,也就是說廣播跟隨activity的生命週期。注意: 在activity結束前,移除廣播接收器。
靜態註冊是常駐型,也就是說當應用程序關閉後,如果有信息廣播來,程序也會被系統調用自動運行。
- 當廣播爲有序廣播時:
- 優先級高的先接收
- 同優先級的廣播接收器,動態優先於靜態
- 同優先級的同類廣播接收器,靜態:先掃描的優先於後掃描的,動態:先註冊的優先於後註冊的。
- 當廣播爲普通廣播時:
- 無視優先級,動態廣播接收器優先於靜態廣播接收器
- 同優先級的同類廣播接收器,靜態:先掃描的優先於後掃描的,動態:先註冊的優先於後註冊的。
Service小結:
- 在Android 中如果要發送一個廣播必須使用sendBroadCast 向系統發送對其感興趣的廣播接收器中。
- 使用廣播必須要有一個intent 對象必設置其action動作對象
- 使用廣播必須在配置文件中顯式的指明該廣播對象
- 每次接收廣播都會重新生成一個接收廣播的對象
- 在BroadCastReceiver中儘量不要處理太多邏輯問題,建議複雜的邏輯交給Activity 或者 Service 去處理
- 如果在AndroidManifest.xml中註冊,當應用程序關閉的時候,也會接收到廣播。在應用程序中註冊就不產生這種情況了。
ContentProvider
contentprovider是android四大組件之一的內容提供器,它主要的作用就是將程序的內部的數據和外部進行共享,爲數據提供外部訪問接口,被訪問的數據主要以數據庫的形式存在,而且還可以選擇共享哪一部分的數據。這樣一來,對於程序當中的隱私數據可以不共享,從而更加安全。contentprovider是android中一種跨程序共享數據的重要組件。
自定義的內容提供者沒用過,因爲沒有實際的業務需求,系統的內容提供者用的比較多,所以具體也不知道該如何記錄ContentProvider