【Android】四大元件歸納總結
阿新 • • 發佈:2020-03-15
> 隨著學習持續更新
四大元件均可使用`android:process="name"`在Manifest中宣告成獨立程序
## Activity
#### 生命週期
![image-20200122100121384](https://developer.android.google.cn/guide/components/images/activity_lifecycle.png?hl=zh-cn)
#### 4種啟動模式
Android使用回退棧來管理Activity例項。當前顯示的Activity在棧頂,當點選後退或返回時,棧頂的Activity出棧。
可以指定Activity的啟動模式來避免重複建立同一Activity
在AndroidManifest.xml中宣告Activity的啟動模式
```xml
```
- standard
預設的啟動模式,允許Activity被多次**例項化**,一個任務棧中會有多個Activity例項
- singleTop
處於棧頂的Activity會被重用,若不在棧頂則會被重新建立。重用時會呼叫原來例項的`onNewIntent()`函式
- singleTask(常用)
一個任務棧只允許存在一個Activity例項,當`startActivity()`時,若該Activity在棧內,則會將該Activity上的所有Activity銷燬,使該Activity處於棧頂,並呼叫`onNewIntent()`方法
- singleInstance
一個Activity在獨立的任務中開啟,保證在系統中只有一個例項,所有的`startActivity()`都會重用該例項,並回調`onNewIntent()`方法
#### 兩個Activity互相切換時的生命週期
A:onCreate->onStart->onResume
這是在A中啟動B活動,生命週期如下:
A: onPause
B: onCreate->onStart->onResume
A: onStop
從B中返回A活動時
B: onPause
A: onRestart->onStart->onResume
B: onStop->onDestroy
## Service
> [https://blog.csdn.net/javazejian/article/details/52709857](https://blog.csdn.net/javazejian/article/details/52709857)
當程式進入後臺執行時,所需要做的操作可以通過Service實現。
在任何位置呼叫`startService()`啟動服務。
每個服務只存在一個例項,每次呼叫`startService()`時會回撥`onStartCommand()`;只需要**呼叫一次**`stopService()`或`stopSelf()`函式,服務會被停止。
**普通Service執行在UI執行緒**,若需要執行耗時操作需要新開執行緒。
#### 生命週期
- ` onCreate()`
- `onStartCommand(intent, flags, startId)`
有三種返回值
- START_STICKY:當服務因記憶體不足被kill掉後,記憶體空閒時會嘗試重建服務,重建成功則回撥`onStartCommand()`,這是傳入的intent為null
- START_NOT_STICKY:當Service因記憶體不足而被系統kill後,即使系統記憶體再次空閒時,系統也不會嘗試重新建立此Service
- START_REDELIVER_INTENT:當Service因記憶體不足而被系統kill後,則會重建服務,並通過傳遞給服務的最後一個 Intent 呼叫 `onStartCommand()`,這個值適用於主動執行應該立即恢復的作業(例如下載檔案)的服務
- `onDestroy()`
呼叫`stopService()`或`stopSelf()`
#### IntentService
重寫`onHandleIntent()`函式,在函式中完成耗時操作。IntentService會自動將操作執行在子執行緒中,並在完成時呼叫`stopSelf()`自我銷燬
```java
public class MyIntentService extends IntentService {
@Override
protected void onHandleIntent(Intent intent) {
...
}
}
```
#### Binder(與服務連線)
當服務僅限本地應用使用,不需要跨程序工作,則可以實現自有的Binder類,讓客戶端通過該類直接訪問服務中的公共方法。
首先需要建立ServiceConnection物件,代表與服務的連線,有兩個方法
- `onServiceConnected(name, serivce)`
系統會呼叫該方法傳遞服務的`onBind()`方法返回的IBinder, 通過該物件可以呼叫獲取到Service的例項物件,進而呼叫服務端的公共方法。
- `onServiceDisconnected(name)`
系統與服務意外中斷時呼叫,unBind不會呼叫該方法
呼叫`bindService(intent, ServiceConnection, flag)`繫結相關服務,flag指繫結時是否自動建立Service,0表示不建立;BIND_AUTO_CREATE表示自動建立。
呼叫`unbindService(ServiceConnection)`
**當最後一個客戶端與服務取消繫結時,系統會將服務銷燬**
#### 前臺服務
- `startForeground(int id, Notification notification)`
將當前服務設成前臺服務,id引數為唯一標識通知的整型數,不得為0
- `stopForeground(boolean removeNotification)`
Android8.0後需要開啟前臺服務要在Activity中`startForegroundService(i)`,且之後Service要在5s內呼叫`startForeground()`才能成功建立前臺服務
#### 如何保證Service不被殺死
- 記憶體資源不足
- 將`onStartCommand()`返回值設成START_STICKY或START_REDELIVER_INTENT,這樣記憶體組後也會恢復服務
- 將服務設成前臺服務,具備較高優先順序
- 使用者手動干預
如果不是force stop則會呼叫生命週期中的`onDestroy()`方法,可以在方法中傳送廣播重啟服務。完備一些的話就啟動兩個服務,相互監聽,相互重啟。
## Broadcast
> [https://www.jianshu.com/p/ca3d87a4cdf3](https://www.jianshu.com/p/ca3d87a4cdf3)
組成:傳送廣播的Broadcast,接受廣播的BroadcastReceiver和傳遞訊息的Intent。
型別:普通廣播、有序廣播、本地廣播(LocalBroadcast)、Sticky廣播
#### 靜態廣播與動態廣播
廣播可分為靜態註冊和動態註冊兩種形式
- 靜態註冊
在Manifest.xml中宣告靜態廣播
```xml
```
- 動態註冊
可以在`onCreate`的時候註冊
```java
MyBroadcastReceiver receiver = new MyBroadcastReceiver();
IntentFilter filter = new IntentFilter("my.action");
context.registerReceiver(receiver, filter);
```
在`onDestroy`的時候登出
```java
unregisterReceiver(receiver);
```
- 靜態廣播與動態廣播的區別
1. 靜態廣播在activity登出的時候也能夠繼續接收;動態廣播在APP退出後就無法接收了
2. 動態廣播在相同Priority下優先順序比靜態廣播高
#### 普通廣播
非同步廣播,呼叫`sendBroadcast(new Intent(ACTION))`來發出廣播
定義廣播接收器
```java
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
...
}
}
```
在AndroidManifest.xml中註冊:
```xml
```
動態註冊接收器:
```java
registerReceiver(new MyBroadcastReceiver(), new IntentFilter(MY_ACTION));
```
#### 有序廣播
傳送出去的廣播被廣播的接收者按照先後順序接收
接收的順序排序
- 按照Priority屬性值從大到小
- Priority相同則動態註冊廣播優先
#### 本地廣播
只限於應用的廣播
使用`LocalBroadcastManager.getInstance(context)`來使用關於廣播的操作函式:
- `registerReceiver(receiver, intentFilter)`
- `unregisterReceiver(receiver)`
- `sendBroadcast(new Intent(INTENT_NAME))`
- `sendBroadcastSync(new Intent())`
註冊本地廣播
```java
mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);
mReceiver = new MyBroadcastReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_MY_TYPE);
mLocalBroadcastManager.registerReceiver(mReceiver,filter);
```
需要在`onDestory()`的中進行登出:
```java
mLocalBroadcastManager.unregisterReceiver(mReceiver)
```
## ContentProvider
ContentProvider可以將應用中的資料共享給其他應用訪問,其他應用可以通過ContentProvider對應用中的資料進行增刪改查。
也可以進行程序間資料的互動和共享,跨程序