Activity 專講

0 前言

做爲 Android 開發中的四大組件之一以及 Android 設備與用戶交互的媒介, Activity 的相關用法應做爲 Android 開發入門學習的重要知識點。android

1 註冊 Activity

在建立HelloWord 工程時, AndroidStudio 會生成一個 AndroidManifest.xml 文件。並添加了相似於下面的代碼。git

<activity android:name=".MainActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
複製代碼

AndroidManifest.xml 文件,顧名思義是一個清單文件,包含四大組件的註冊、權限聲明、應用配置等。上述代碼中標籤 activity 表示註冊一個名爲 MainActivityActivitygithub

intent-filter 標籤做用暫不講解,只須要知道用在這裏的意思是這個 Activity 是程序的入口,它不是必須存在的。註冊 Activity 最簡單的代碼只需一行。ide

<activity android:name=".MainActivity"/>
複製代碼

android:name 使用的是相對路徑,拼接上 package 便是完整的類路徑。使用完整路徑以下。學習

<activity android:name="com.flueky.demo.MainActivity"/>
複製代碼

2 Activity 跳轉

當一個應用存在多個頁面時,A 頁面須要跳轉到 B 頁面,實際是 A Activity 切換到 B Activity 。兩個 Activity 之間切換的代碼主要有 3 個。動畫

2.1 startActivity

跳轉 Activity 的最基本方法,擴展方法以下。ui

/** * 跳轉 Activity,intent 包含須要打開的 Activity 信息、Action 及 Extras */
public void startActivity(Intent intent);

/** * 支持帶參數的跳轉。雖然同 Extras 類型一致,可是不能夠自定義key,建議經過 ActivityOptions 類構建出 Bundle 對象。 API 16 才支持。 */
public void startActivity(Intent intent, @Nullable Bundle options);

/** * 同時加載多個 Activity 。可是隻顯示最後一個 Activity,並將以前的 Activity 入棧。API 11 才支持。 */
public void startActivities(Intent[] intents);

/** * 用法見上。 */
public void startActivities(Intent[] intents, @Nullable Bundle options);
複製代碼

下面演示了 startActivity(Intent , Bundle)startActivities(Intent[]) 的使用。 注意 區分 dataoptions 的類型和用途。this

// 跳轉一個 Activity
if (v.getTag().toString().equals("single")) {
    Intent intent = new Intent(this, SecondActivity.class);
    Bundle data = new Bundle();
    data.putString("key","flueky");
    intent.putExtras(data);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
        // 指定 Activity 跳轉動畫選項
        Bundle options = ActivityOptions.makeCustomAnimation(this, R.anim.activity_enter, R.anim.activity_exit).toBundle();
        startActivity(intent, options);
    }
} else {
    // 跳轉多個 Activity
    Intent[] intent = new Intent[2];
    intent[0] = new Intent(this, SecondActivity.class);
    intent[1] = new Intent(this, ThirdActivity.class);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        // 同時打開兩個 Activity ,可是隻會顯示 ThirdActivity 。可是 SecondActivity 在 Activity 棧中。
        // finish ThirdActivity 會顯示 SecondActivity 。
        startActivities(intent);
    }
}
複製代碼

2.2 startActivityForResult

這個方法是對 startActivity 的補充。一樣具備上面四個重載和關聯方法。url

不一樣處在於,這個方法須要和 setResult 方法關聯使用。 A activity 執行 startActivityForResult 方法顯示 B activity ,須要 B activity 在 finish 以前執行 setResult 方法。然後在 A activity 重寫 void onActivityResult(int requestCode, int resultCode, Intent data) 方法,處理 B activity 回傳過來的標記或數據。spa

雖然這種 Activity 之間數據交互的方式已經被 EventBus 取代,可是入門 Android 開發仍然須要掌握。

public void jump(View v) {
       
    if (v.getTag().toString().equals("single")) {
        ......
    } else if(v.getTag().toString().equals("result")){
        Intent intent = new Intent(this, ThirdActivity.class);
        // 輸出日誌,查看 intent 及其 hashcode
        Log.d("intent", "jump: "+intent+" "+intent.hashCode());
        startActivityForResult(intent,123);
    }
}

/** * 示例代碼,一般不建議這種寫法 */
@Override
public void finish() {

    Intent intent = getIntent();
    // 輸出日誌,查看 intent 及其 hashcode
    Log.d("intent", "finish: "+intent+" "+intent.hashCode());
    // 能夠經過 intent 攜帶須要回傳的數據
    // 以及能夠經過 resultcode 傳回標識
    setResult(111,intent);
    super.finish();
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    // 輸出日誌,查看 intent 及其 hashcode
    Log.d("intent", "onActivityResult: "+data+" "+data.hashCode());
    // 輸出 requestcode 和 resultcode 
    Log.e("intent", "onActivityResult: "+requestCode+" "+resultCode);
}

複製代碼

輸出日誌:

com.flueky.demo D/intent: jump: Intent { cmp=com.flueky.demo/.ThirdActivity } 11794772
com.flueky.demo D/intent: finish: Intent { cmp=com.flueky.demo/.ThirdActivity } 132627786
com.flueky.demo D/intent: onActivityResult: Intent { cmp=com.flueky.demo/.ThirdActivity } 177493179
com.flueky.demo E/intent: onActivityResult: 123 111
複製代碼

經過分析日誌看出:三處的 intent 實例不是同一個對象,但倒是相同的內容。

2.3 finish

因爲 Android 中對 Activity 的管理是經過棧的方式。因此 A activity 到 B activity 會將 B activity 入棧,A activity 在 B 的下層。如須要再從 B activity 回到 A activity。能夠經過 startActivity 方式,也能夠直接 經過 finish 方式銷燬 B activity 並出棧,使 A activity 回到棧頂便可。

具體使用 startActivity 仍是 finish 視使用場景。可是在學習了後面的啓動模式後,能夠經過指定啓動模式,實現 startActivityfinish 相同的效果。

finish 方法使用很簡單。

public void back(View v){
    finish();
}
複製代碼

3 生命週期

如圖,是官方提供的 Android 生命週期執行的流程圖。一共 七個生命週期方法。

  1. onCreate

Activity 實例在建立後執行此方法。

執行 setContentViewActivity 與 layout 資源綁定。

  1. onStart

Activity 建立後,顯示在頁面時執行此方法。

  1. onResume

Activity 顯示在頁面後能夠響應用戶點擊事件時執行此方法。

  1. onPause

Activity 切換到後臺時,執行此方法,此時再也不響應用戶事件。ss

  1. onStop

Activity 對用戶不可見時,執行此方法。

  1. onDestory

Activity 實例被銷燬時,執行此方法。

  1. onRestart

Activity 進入後臺沒有被銷燬時,再次顯示此 Activity 會執行此方法。

驗證生命週期方法執行結果以下:

啓動程序,進入 MainActivity
2019-02-24 14:35:32.324 27958-27958/com.flueky.demo D/MainActivity: heheda onCreate
2019-02-24 14:35:32.491 27958-27958/com.flueky.demo D/MainActivity: heheda Start
2019-02-24 14:35:32.500 27958-27958/com.flueky.demo D/MainActivity: heheda Resume
startActivity,進入 ThirdActivity
2019-02-24 14:35:42.407 27958-27958/com.flueky.demo D/MainActivity: heheda Pause
2019-02-24 14:35:42.440 27958-27958/com.flueky.demo D/ThirdActivity: heheda onCreate
2019-02-24 14:35:42.456 27958-27958/com.flueky.demo D/ThirdActivity: heheda Start
2019-02-24 14:35:42.457 27958-27958/com.flueky.demo D/ThirdActivity: heheda Resume
2019-02-24 14:35:42.962 27958-27958/com.flueky.demo D/MainActivity: heheda Stop
finish ,回到 MainActivity
2019-02-24 14:35:45.921 27958-27958/com.flueky.demo D/ThirdActivity: heheda Pause
2019-02-24 14:35:45.938 27958-27958/com.flueky.demo D/MainActivity: heheda Restart
2019-02-24 14:35:45.939 27958-27958/com.flueky.demo D/MainActivity: heheda Start
2019-02-24 14:35:45.939 27958-27958/com.flueky.demo D/MainActivity: heheda Resume
2019-02-24 14:35:46.436 27958-27958/com.flueky.demo D/ThirdActivity: heheda Stop
2019-02-24 14:35:46.436 27958-27958/com.flueky.demo D/ThirdActivity: heheda Destroy
按下home鍵 ,回到 手機桌面
2019-02-24 14:35:50.950 27958-27958/com.flueky.demo D/MainActivity: heheda Pause
2019-02-24 14:35:51.007 27958-27958/com.flueky.demo D/MainActivity: heheda Stop
再次進入程序 ,顯示 MainActivity
2019-02-24 14:35:58.095 27958-27958/com.flueky.demo D/MainActivity: heheda Restart
2019-02-24 14:35:58.100 27958-27958/com.flueky.demo D/MainActivity: heheda Start
2019-02-24 14:35:58.101 27958-27958/com.flueky.demo D/MainActivity: heheda Resume

3 添加跳轉動畫

Activity 添加跳轉動畫,已知有三種實現方式。

  1. startActivity 時指定 options 參數。見上。
  2. overridePendingTransition 指定區間動畫。API 5 支持。
  3. 重寫 AppTheme ,設置動畫。之後在動畫章節會講。
/** * startActivity 方法最後也會執行到 startActivityForResult */
@Override
public void startActivityForResult(Intent intent, int requestCode) {
    super.startActivityForResult(intent,requestCode);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ECLAIR) {
        // 指定區間動畫
        overridePendingTransition(R.anim.activity_enter,R.anim.activity_exit);
    }
}

@Override
public void finish() {
    super.finish();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ECLAIR) {
        // 指定區間動畫
        overridePendingTransition(R.anim.activity_enter,R.anim.activity_exit);
    }
}

複製代碼

重寫上面兩個方法後,在每次 startActivityfinish 方法執行時,會自動添加動畫效果。

4 啓動模式

  1. standard

每次執行 startActivity 方法,都會新生成一個 Activity 實例併入棧。

  1. singleTop

若是 A activity 已經在棧頂,再次 start A activity 時。不從新建立 A activity 實例,複用以前的 A activity 實例。

生命週期方法:A.onPause->A.onNewIntent->A.onResume

  1. singleTask

特殊狀況具有 singleTop 的屬性。通常狀況下,若是 A activity 實例在棧中,當前顯示 B activity 即棧頂是 B activity 實例。B activity start A activity 時,B activity 實例出棧。A activity 實例在棧頂。

生命週期方法:B.onPause->A.onNewIntent->A.onRestart->A.onStart->A.onResume->B.onStop->B.onDestory

  1. singleInstance

具有 singleTop 的屬性。可是,activity 實例會單獨存在於一個棧中。

源碼地址

以爲有用?那打賞一個唄。[去打賞]({{ site.url }}/donate/)

相關文章
相關標籤/搜索