1. Activity
1.1. 安卓中的Activity定義和特性:
- 一個Activity就是一個屏幕頁面
- 一個APP中有很多個Activity(打開郵件app,打開具體郵件)
- APP一般從MainActivity中啟動的,當然了,這個也可以修改的
- APP內的Activity可以通過一些方法(Intent...)進行切換(打開郵件app -> 打開具體郵件)
- APP之間的Activity也可以互相切換(從瀏覽器頁面 -> facebook頁面)
1.2. 注冊Activity
進入AndroidManifest.xml在application下添加一個activity元素
1. Intent filters:設置默認開啟的activity
Intent filters可以顯示或者隱式的啟動activity,我們可以利用這個屬性來擴展activity功能
<activity
android:name=".MainActivity"
android:label="FirstPage"
android:icon="@drawable/app_icon">
<!--intent-filter放在哪個activity,這個actiivty就是默認啟動的activity-->
<intent-filter>
<!--action:這個activity可以發送數據-->
<action android:name="android.intent.action.SEND" />
<!--category:這個activity可以接收請求-->
<category android:name="android.intent.category.DEFAULT" />
<!--data:這個activity可以接收數據類型-->
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
<activity
android:name=".SecondActivity"
android:label="SecondPage"
></activity>
程序調用過程
// Create the text message with a string
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.setType("text/plain");
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
// Start the activity
startActivity(sendIntent);
1.3. Activity的啟動流程
插入activity01.md
插入activity02.md
1.4. 如何控制activity中的內容
通過代表控件的對象來更改控件內容
2. Android的生命周期
首先我們來看一下谷歌官網發布的圖

| 聲明周期函數 | 調用時機 | 所處狀態 | 應該執行的操作 |
|---|---|---|---|
onCreate |
在Activity對象第一次創建時調用 | Created | 初始化操作(只執行一次的操作) 調用 setContentView()設置界面布局 |
onStart |
當Activity變得可見時調用該函數 | Started | 組件的初始化操作,建議放再onResume中 |
onResume |
當Activity開始准備與用戶交互時調用該方法 | Resumed | 最常見的操作都需要放在這里(最重要的部分) |
onPause |
當系統即將開啟另外一個Activity之前調用 | Paused | 停止一些可能影響電池的操作,清除一些輕度的占用CPU任務(關閉相機) |
onStop |
當前Activity變得不可見時調用 | Stopped | 當屏幕不可見的時候,清除或者調整一些操作 保存數據庫的最好位置 |
onDestroy |
當前Activity被銷毀之前將會調用 | 清除所有占用內存的任務 | |
onRestart |
當一個Activity再起啟動之前會調用 | -> Resumed |
onCreate()
- 作用: 初始化 + 進入啟動階段
- 在Activity對象第一次被創建時調用,必須重寫
- 那么在
onCreate()應該執行一些什么操作呢?- 在整個生命周期只需要執行一次的操作
- 初始化 Activity 的必需組件
- 調用
setContentView()來定義用戶界面的布局
- 接收的參數為
savedInstanceState:表示活動前所保存的狀態,如果這個活動之前沒有啟動過,那么Bundle的值為null onCreate()之后:進入啟動階段
TextView mTextView;
// some transient state for the activity instance
String mGameState;
@Override
public void onCreate(Bundle savedInstanceState) {
// 調用父類的onCreate方法
super.onCreate(savedInstanceState);
// recovering the instance state
if (savedInstanceState != null) {
mGameState = savedInstanceState.getString(GAME_STATE_KEY);
}
// 設置界面布局文件(res/layout/main_activity.xml)
setContentView(R.layout.main_activity);
// 初始化一些部件,這樣在下面的方法中可以操作
mTextView = (TextView) findViewById(R.id.text_view);
}
// This callback is called only when there is a saved instance that is previously saved by using
// onSaveInstanceState(). We restore some state in onCreate(), while we can optionally restore
// other state here, possibly usable after onStart() has completed.
// The savedInstanceState Bundle is same as the one used in onCreate().
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
mTextView.setText(savedInstanceState.getString(TEXT_VIEW_KEY));
}
// invoked when the activity may be temporarily destroyed, save the instance state here
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putString(GAME_STATE_KEY, mGameState);
outState.putString(TEXT_VIEW_KEY, mTextView.getText());
// call superclass to save any view hierarchy
super.onSaveInstanceState(outState);
}
onStart()
- 作用: 使Activity可見,可視化頁面會顯示出來 + 進入Resume階段
- 特性:
- 完成得特別快
- 一旦執行完成,直接進入
onResume()階段 - 所有生命周期組件會收到
onStart()事件
onResume()
- 作用: app可以和用戶交互
- 特性:
- app會一直停留在這個階段,直到有什么操作打斷他(來電話啦...)
- 所有生命周期組件會收到
onResume()事件 - 當有異常時,會進入暫停階段,處罰
onPause()方法 - 當異常結束重新進入Resume階段時,又會重新調用
onResume() - 你應該在這段代碼中寫一些初始化組件的代碼
- 建議: 如果在
onStart()中初始化一些組件后,記得在onStop()釋放
onPause()
- 當acitivty不再前端的時候(即使在多窗口模式中,它是visible模式), app進入這個階段
- 使用
onPause()方法來停止或者調整操作,當activity不再主界面的時候 - acitivity進入這個階段的原因如下:
- 一些中斷了app運行
- 多窗口模式下,一個app啟動會自動讓另外的app進入onpause狀態
- 有些情況下,即使activity是visible模式,它也會進入這個onPause階段
- 所有生命周期組件會收到
onPause()事件,這里我們可以停止一些操作 - 這個階段的任務:
- 可以停止一些你不想運行的操作(關閉camera..)
- 釋放一些系統資源,處理sensors或者其他會影響電源的組件(但是推薦使用onStop()方法)
- 千萬不要在這里保存數據,網絡操作,或者數據庫操作
- 注意: 完成這個階段並不意味着activity離開了onPause階段,如果acitivty進入Resume階段,調用
onResume,如果actiivty完全不可見,進入onStop()階段,否則一直在onPause階段
public class JavaCameraComponent implements LifecycleObserver {
...
// 一旦收到`onPause`事件。釋放camera
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void releaseCamera() {
if (camera != null) {
camera.release();
camera = null;
}
}
...
}
onStop()
- 什么時候發生:activity完全不可見
- 所有生命周期組件會收到
onStop()事件,這里我們可以停止一些操作 - 在這個階段的任務
- 釋放一些heavy的任務
- 關閉一些CPU重的任務
- 這是保存到數據庫的絕佳位置
@Override
protected void onStop() {
// call the superclass method first
super.onStop();
// save the note's current draft, because the activity is stopping
// and we want to be sure the current note progress isn't lost.
ContentValues values = new ContentValues();
values.put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText());
values.put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle());
// do this update in background on an AsyncQueryHandler or equivalent
mAsyncQueryHandler.startUpdate (
mToken, // int token to correlate calls
null, // cookie, not used here
mUri, // The URI for the note to update.
values, // The map of column names and new values to apply to them.
null, // No SELECT criteria are used.
null // No WHERE columns are used.
);
}
onDestroy()
- 進入這個階段的原因:
- activity完成(用戶取消activity,或者調用了finish()方法)
- 系統自動刪除activity(手機轉動,或者多窗口模式下)
- 所有生命周期組件會收到
onDestroy()事件,這里我們可以所有需要停止的東西
3. Activity生命周期被回收的幾率表
| 被殺的可能性 | 過程狀態 | Activity狀態 |
|---|---|---|
| 最小 | 前端 | Created Started Resumed |
| 中等 | 后端(lost focus) | Paused |
| 最高 | 后端(不可見) 空 |
Stopped destroyed |
4. 保存和儲存短暫的UI狀態
考慮如下兩種情況
- 用戶轉換屏幕或者切換到多窗口模式時,系統會默認摧毀之前的activity,但是用戶希望能夠保持原來的activity不變
- 用戶有時候可能一不小心從當前app切換到其他app,系統會默認摧毀之前的activity,當然我們希望用戶切換回來的時候還是保持當前的狀態
解決方法: 保存UI狀態:ViewModel + obSaveInstanceState()
4.1. Instance state
- 系統用於保存之前狀態的過程為
Instance state--其實是一些保存在Bundle對象的鍵值對 - 系統默認使用
Bundle的Instance state來保存每個View的信息(比如EditText中的文本)
4.2.通過onSaveInstanceState()保存一些輕度,簡單的UI狀態
- 當Activity准備停止的時候,系統就會調用
onSaveInstanceState()來保存一些基本的信息,比如edittext中的value.. - 如果你想要保存更多的內容,需要重寫
onSaveInstanceState()方法,添加新的key-value對到Bundle對象中 - 如果重寫
onSaveInstanceState()方法,一定調用super implmenetaion
static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";
// ...
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the user's current game state
savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}
4.3. 通過保存的UI狀態恢復活動的UI
- 我們可以在
onCreate和onRestoreInstanceState()中調用Bundle對象來恢復UIonCreate:只有當創建一個新的activtiy實例,才會調用這個方法,必須堅持Bundle是否為空,空的話,創建新的實例,不是空的話,恢復之前的UIonRestoreInstanceState():這個方法在onStart()方法之后調用,系統只會在Bundle不為空的時候調用,所以你不用檢查是否為null
// method 1
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // Always call the superclass first
// Check whether we're recreating a previously destroyed instance
if (savedInstanceState != null) {
// Restore value of members from saved state
mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
} else {
// Probably initialize members with default values for a new instance
}
// ...
}
// method2
public void onRestoreInstanceState(Bundle savedInstanceState) {
// Always call the superclass so it can restore the view hierarchy
super.onRestoreInstanceState(savedInstanceState);
// Restore state members from saved instance
mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
}
5.Activity之間是如何切換的?
5.1 從一個Activity切換到另外一個Activity:
1. startActivity()
- 如果不需要返回一個結果,就用這個
Intent intent = new Intent(this, SignInActivity.class);
startActivity(intent);
你也可以通過startActivity啟動一些以后的組件來擴展功能(調用Email的app)
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
startActivity(intent);
The EXTRA_EMAIL extra added to the intent is a string array of email addresses to which the email should be sent. When an email application responds to this intent, it reads the string array provided in the extra and places them in the "to" field of the email composition form. In this situation, the email application's activity starts and when the user is done, your activity resumes.
2.startActivityForResult()
- 當你需要從即將結束的Activity中返回一個值的時候用這個,比如你從當前activity的列表中選中一個水果,你想要保存這個選中的水果
- 當有一個子類Activity的時候,它可以調用
setResult(int)來返回數據給他的父類Activity - 父類Activity使用
onActivityResult(int, int, Intent)來獲取信息
public class MyActivity extends Activity {
// ...
static final int PICK_CONTACT_REQUEST = 0;
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
// When the user center presses, let them pick a contact.
startActivityForResult(
new Intent(Intent.ACTION_PICK,
new Uri("content://contacts")),
PICK_CONTACT_REQUEST);
return true;
}
return false;
}
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
if (requestCode == PICK_CONTACT_REQUEST) {
if (resultCode == RESULT_OK) {
// A contact was picked. Here we will just display it
// to the user.
startActivity(new Intent(Intent.ACTION_VIEW, data));
}
}
}
}
6.Activity的幾種狀態
| 狀態 | 產生原因 | 調用方法 |
|---|---|---|
| 配置變化 | 轉屏幕 更改語言 插入設備 |
原activity被銷毀:onPause()->onStop()->onDestroy() 原activity被重建:onCrate()->onStart()->onResume() |
| 新的activity或者對話框顯示 | 比如彈出一個對話框-> 導致被覆蓋的activity暫停 | 新的activity半覆蓋: onPause()>onResume() 新的activity全覆蓋:onPause()->onStop()->onRestart()->onStart()->onResume() |
| 點擊返回按鈕 | 點擊Back按鈕 |
原activity: onPause()->onStop()->onDestroy()->remove from back stack onSaveInstanceState() not work 你可以重寫 onBaclPressed |
| 系統殺死app | 系統需要釋放內存 | .... |
7.實例演示Activity的生命周期
創建兩個activity: mainactivity和otheractivity
public class OtherActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_other);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
System.out.println("--OtherActivity: OnCreate--");
}
@Override
protected void onStart() {
super.onStart();
System.out.println("--OtherActivity: OnStart--");
}
@Override
protected void onResume() {
super.onResume();
System.out.println("--OtherActivity: OnResume--");
}
@Override
protected void onPause() {
super.onPause();
System.out.println("--OtherActivity: OnPause--");
}
@Override
protected void onStop() {
super.onStop();
System.out.println("--OtherActivity: OnStop--");
}
@Override
protected void onDestroy() {
super.onDestroy();
System.out.println("--OtherActivity: OnDestroy--");
}
@Override
protected void onRestart() {
super.onRestart();
System.out.println("--MainActivity: OnRestart--");
}
}
otherActivity也差不多,然后執行程序

當程序呈現第一個頁面的時候,打印的信息是:

當點擊按鈕,進入第二個activity的時候:

當點擊返回按鈕返回主activity的時候:

