玩轉Android之Activity詳細剖析

 

     本文主講了什麼是Activity,它的生命週期,不對的操作,調用了什麼函數。以及不同的Activity之間的跳轉、數據傳遞等。

     Activity 是用戶接口程序,原則上它會提供給用戶一個交互式的接口功能。它是 android 應用程序的基本功能單元。Activity 本身是沒有界面的。所以activity類創建了一個窗口,開發人員可以通過setContentView(View)接口把UI放到activity創建的窗口上,當activity指向全屏窗口時,也可以用其他方式實現:作爲漂浮窗口(通過windowIsFloating的主題集合),或者嵌入到其他的activity(使用ActivityGroup)。activity是單獨的,用於處理用戶操作。幾乎所有的activity都要和用戶打交道。

一、Activity的生命週期簡介

1、操縱生命週期的七種方法:

圖片1

 

2、Activity的運作流程

  • 一般啓動Activity:onCreate -> onStart -> onResume

  • 呼叫另一個Activity: onPause -> onCreate -> onStart -> onResume -> onStop

  • 還原Activity: onPause -> onRestart -> onStart -> onResume -> onStop -> onDestroy

  • 退出Activity: onPause -> onStop -> onDestroy

  • 回收再啓動Activity: onCreate -> onStart –> onResume

3、Activity生命週期的四種基本狀態:

(1)Active/Runing:一個新 Activity 啓動入棧後,它在屏幕最前端,處於棧的最頂端,此時它處於可見並可和用戶交互的激活狀態。

(2)Paused:當 Activity 被另一個透明或者 Dialog 樣式的 Activity 覆蓋時的狀態。此時它依然與窗口管理器保持連接,系統繼續維護其內部狀態,所以它仍然可見,但它已經失去了焦點故不可與用戶交互。

(3)Stoped。當 Activity 被另外一個 Activity 覆蓋、失去焦點並不可見時處於 Stoped狀態。

(4)Killed Activity。被系統殺死回收或者沒有被啓動時處於 Killed狀態。

 

QQ截圖20150319192442

二、Activity生命週期代碼範例

   1: /**
   2:  *Activity生命週期學習
   3:  *@author 林炳文(博客 )
   4:  *@time 2015.3.19
   5:  */
   6: package com.example.activitylearning;
   7: import android.os.Bundle;
   8: import android.app.Activity;
   9: import android.util.Log;
  10: public class MainActivity extends Activity {
  11:     private static final String TAG="AvtivityTest";
  12:     @Override
  13:     protected void onCreate(Bundle savedInstanceState) {
  14:         super.onCreate(savedInstanceState);
  15:         Log.d(TAG, "onCreate() called");
  16:         setContentView(R.layout.activity_main);
  17:     }
  18:     @Override
  19:     protected void onStart(){
  20:         super.onStart();
  21:         Log.d(TAG, "onStart() called");
  22:
  23:     }
  24:     @Override
  25:     protected void onResume(){
  26:         super.onResume();
  27:         Log.d(TAG,"onResume() called");
  28:
  29:     }
  30:     @Override
  31:     protected void onPause(){
  32:         super.onPause();
  33:          Log.d(TAG, "onPause() called");
  34:
  35:     }
  36:     @Override
  37:     protected void onStop(){
  38:         super.onStop();
  39:          Log.d(TAG, "onStop() called");
  40:
  41:     }
  42:     protected void onDestroy(){
  43:         super.onDestroy();
  44:          Log.d(TAG, "onDestroy() called");
  45:
  46:     }
  47:
  48:
  49: }

 

1、程序啓動

  • 一般啓動Activity:onCreate -> onStart -> onResume

a1

 

2、程序啓動後按下後退鍵

  • 退出Activity: onPause -> onStop -> onDestroy

a2

可以看到,程序已退出了。

3、程序啓動後按下主屏幕鍵

  • 還原Activity: onPause -> onRestart -> onStart -> onResume -> onStop -> onDestroy

a3

再打開程序:

 

a4

 

三、多個Activity管理

1、Android 是通過一種 Activity 棧的方式來管理 Activity 的,一個 Activity 的實例的狀態決定它在棧中的位置。

2、處於前臺的 Activity 總是在棧的頂端,當前臺的 Activity 因爲異常或其它原因被銷燬時,處於棧第二層的 Activity 將被激活,上浮到棧頂。

3、當新的 Activity 啓動入棧時,原 Activity 會被壓入到棧的第二層。一個 Activity 在棧中的位置變化反映了它在不同狀態間的轉換

QQ截圖20150319195450

注意:

在Android系統中,要使用Activity必須在AndroidManifest.xml文件中進行配置。

在<application…/>元素中添加<activity…/>子元素即可

配置Activity通常指定如下三個屬性:

–name:指定該Activity的實現類。

–icon:指定該Activity對應的圖標。

–label:指定該Activity的標籤。


四、由一個Activity啓動另一個Activity(不帶數據傳遞)

1、佈局

activity_1.xml(放在layout)

   1: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   2:     xmlns:tools="http://schemas.android.com/tools"
   3:     android:layout_width="match_parent"
   4:     android:layout_height="match_parent"
   5:     tools:context=".Activity1" >
   6: <Button
   7:     android:id="@+id/id_button1"
   8:     android:layout_width="match_parent"
   9:     android:layout_height="wrap_content"
  10:     android:text="啓動Activity2"
  11:     />
  12: </RelativeLayout>

activity_2.xml

   1: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   2:     xmlns:tools="http://schemas.android.com/tools"
   3:     android:layout_width="match_parent"
   4:     android:layout_height="match_parent" >
   5: <Textview
   6:     android:text="歡迎來到Activity2"
   7:     android:layout_centerInParent="true"
   8:     android:layout_width="match_parent"
   9:     android:layout_height="wrap_content"
  10:     android:textSize="30sp"
  11:     />
  12: </RelativeLayout>

2、對應的代碼:

Activity1.java

   1: /**
   2:  *Activity生命週期學習
   3:  *@author 林炳文(博客 http://blog.csdn.net/evankaka/)
   4:  *@time 2015.3.19
   5:  */
   6: package com.example.activitylearning;
   7: import android.os.Bundle;
   8: import android.app.Activity;
   9: import android.content.Intent;
  10: import android.util.Log;
  11: import android.view.View;
  12: import android.view.View.OnClickListener;
  13: import android.widget.Button;
  14: public class Activity1 extends Activity {
  15:     private static final String TAG="Avtivity1";
  16:     private Button mButton;
  17:
  18:     @Override
  19:     protected void onCreate(Bundle savedInstanceState) {
  20:         super.onCreate(savedInstanceState);
  21:         Log.d(TAG, "onCreate() called");
  22:         setContentView(R.layout.activity_1);
  23:         mButton=(Button)findViewById(R.id.id_button1);
  24:         mButton.setOnClickListener(new OnClickListener() {
  25:             @Override
  26:             public void onClick(View arg0) {
  27:                 startActivity(new Intent(Activity1.this,Activity2.class));
  28:
  29:             }
  30:         });
  31:     }
  32:     @Override
  33:     protected void onStart(){
  34:         super.onStart();
  35:         Log.d(TAG, "onStart() called");
  36:
  37:     }
  38:     @Override
  39:     protected void onResume(){
  40:         super.onResume();
  41:         Log.d(TAG,"onResume() called");
  42:
  43:     }
  44:     @Override
  45:     protected void onPause(){
  46:         super.onPause();
  47:          Log.d(TAG, "onPause() called");
  48:
  49:     }
  50:     @Override
  51:     protected void onStop(){
  52:         super.onStop();
  53:          Log.d(TAG, "onStop() called");
  54:
  55:     }
  56:     protected void onDestroy(){
  57:         super.onDestroy();
  58:          Log.d(TAG, "onDestroy() called");
  59:
  60:     }
  61:
  62:
  63: }

Activity2.java

   1: package com.example.activitylearning;
   2:
   3: import android.app.Activity;
   4: import android.os.Bundle;
   5: import android.util.Log;
   6:
   7: public class Activity2 extends Activity {
   8:     private static final String TAG="Avtivity2";
   9:     @Override
  10:     protected void onCreate(Bundle savedInstanceState) {
  11:         super.onCreate(savedInstanceState);
  12:         Log.d(TAG, "onCreate() called");
  13:         setContentView(R.layout.activity_2);
  14:     }
  15:     @Override
  16:     protected void onStart(){
  17:         super.onStart();
  18:         Log.d(TAG, "onStart() called");
  19:
  20:     }
  21:     @Override
  22:     protected void onResume(){
  23:         super.onResume();
  24:         Log.d(TAG,"onResume() called");
  25:
  26:     }
  27:     @Override
  28:     protected void onPause(){
  29:         super.onPause();
  30:          Log.d(TAG, "onPause() called");
  31:
  32:     }
  33:     @Override
  34:     protected void onStop(){
  35:         super.onStop();
  36:          Log.d(TAG, "onStop() called");
  37:
  38:     }
  39:     protected void onDestroy(){
  40:         super.onDestroy();
  41:          Log.d(TAG, "onDestroy() called");
  42:
  43:     }
  44:
  45: }

3、Activity註冊

Androidmanifest.xml中

增加:

   1: <activity
   2:     android:name="com.example.activitylearning.Activity2"
   3:     android:label="@string/app_name">
   4: </activity>

                       image image

4、運行結果

(1)、在Activity中點擊按鈕:啓動Activity2

QQ截圖20150319204607

從上面可以看出Activity1沒被毀掉,而是變成Stop()了,當前變成不可見。

(2 )然後再點擊後退鍵:

 

QQ截圖20150319204640

五、由一個Activity啓動另一個Activity(帶數據傳遞)

1、界面

activity_1.xml(放在layout)

   1: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   2:     xmlns:tools="http://schemas.android.com/tools"
   3:     android:layout_width="match_parent"
   4:     android:layout_height="match_parent"
   5:     tools:context=".Activity1" >
   6: <Button
   7:     android:id="@+id/id_button1"
   8:     android:layout_width="match_parent"
   9:     android:layout_height="wrap_content"
  10:     android:text="啓動Activity2"
  11:     />
  12:
  13: <EditText
  14:     android:id="@+id/id_edittext1"
  15:     android:layout_below="@id/id_button1"
  16:     android:layout_width="match_parent"
  17:     android:layout_height="wrap_content"
  18:     />
  19: <EditText
  20:     android:id="@+id/id_edittext2"
  21:     android:layout_below="@id/id_edittext1"
  22:     android:layout_width="match_parent"
  23:     android:layout_height="wrap_content"
  24:     />
  25: </RelativeLayout>

activity_2.xml(放在layout)

   1: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   2:     xmlns:tools="http://schemas.android.com/tools"
   3:     android:layout_width="match_parent"
   4:     android:layout_height="match_parent" >
   5: <TextView
   6:     android:id="@+id/id_textview1"
   7:     android:layout_width="match_parent"
   8:     android:layout_height="wrap_content"
   9:     android:textSize="30sp"
  10:     />
  11: <TextView
  12:     android:id="@+id/id_textview2"
  13:     android:layout_below="@id/id_textview1"
  14:     android:layout_width="match_parent"
  15:     android:layout_height="wrap_content"
  16:     android:textSize="30sp"
  17:     />
  18: </RelativeLayout>

兩個效果如下:

 

                  imageimage

2、主要代碼。

Activity1.java中

   1: Intent mIntent=new Intent(Activity1.this,Activity2.class);
   2:  String mString1 = mEditText1.getText().toString();
   3:  String mString2 = mEditText1.getText().toString();
   4:  mIntent.putExtra("one",mString1);
   5:  mIntent.putExtra("two",mString2);
   6: startActivity(mIntent);

Activity2.java中

   1: mTextView1=(TextView)findViewById(R.id.id_textview1);
   2: mTextView2=(TextView)findViewById(R.id.id_textview1);
   3:
   4:  String mString1=getIntent().getStringExtra("one");
   5:  String mString2=getIntent().getStringExtra("two");
   6:
   7:  mTextView1.setText(mString1);
   8:  mTextView2.setText(mString1);

3、運行結果

               image               image

左邊爲Activity1,右邊爲Activity2.它會得到Activity1的結果並在TextView中顯示出來

六、得到返回的Activity的數據

這裏要實現在Activity1中的兩個EditText中輸入內容,打開Activity2,將Activity1中的兩個EditText的內容顯示在Activity2的兩個TextView中。

在在Activity2中的兩個EditText中輸入內容,按下返回鍵,將Activity2中的兩個EditText的內容顯示在Activity1的兩個TextView中。

1、佈局

            image         image

2、主要代碼

Activity1.java中:

   1: mButton=(Button)findViewById(R.id.id_button1);
   2:    mButton.setOnClickListener(new OnClickListener() {
   3:        @Override
   4:        public void onClick(View arg0) {
   5:            Intent mIntent=new Intent(Activity1.this,Activity2.class);
   6:             String mString1 = mEditText1.getText().toString();
   7:             String mString2 = mEditText2.getText().toString();
   8:             mIntent.putExtra("one",mString1);
   9:             mIntent.putExtra("two",mString2);
  10:             startActivityForResult(mIntent, 0);
  11:
  12:        }
  13:    });

注意要用 startActivityForResult(mIntent, 0);//0表示標識,等下Activity也要標誌爲0

然後是處理Activity2返回後的事件

   1: @Override
   2: protected void onActivityResult(int requestCode, int resultCode, Intent data) {
   3:     super.onActivityResult(requestCode, resultCode, data);
   4:     if(null==data)
   5:         return;
   6:     TextView  mTextView3=(TextView)findViewById(R.id.id_textview3);
   7:     TextView  mTextView4=(TextView)findViewById(R.id.id_textview4);
   8:
   9:       String mString3=data.getStringExtra("three");
  10:         String mString4=data.getStringExtra("four");
  11:
  12:         mTextView3.setText(mString3);
  13:         mTextView4.setText(mString4);
  14: }

Activity2.java中:

在按下返回鍵的事件中,增加一些數據傳遞,其實這裏主要是setResult(0,result);注意0要和上面的startActivityForResult(mIntent, 0);對應。

   1: @Override
   2: public boolean onKeyDown(int keyCode, KeyEvent event) {
   3:    if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
   4:
   5:        EditText       mEditText3=(EditText)findViewById(R.id.id_edittext3);
   6:        EditText     mEditText4=(EditText)findViewById(R.id.id_edittext4);
   7:        String mData1 = mEditText3.getText().toString();
   8:          String mData2 = mEditText4.getText().toString();
   9:        Intent result = new Intent();
  10:        result.putExtra("three", mData1);
  11:        result.putExtra("four", mData2);
  12:        setResult(0, result);
  13:
  14:    }
  15:    return super.onKeyDown(keyCode, event);
  16: }

3、效果

從Activity1中啓動Activity2,可以看到,數據傳遞過去了

           image                image

 

                                Activity1                                        Activity2

從Activity2中返回到Activity1中,可以看到,數據返回了

            image      image

                                   Activity2                                        Activity1

八、額外內容

Activity返回值

    使用startActivity方式啓動的Activity和它的父Activity無關,當它關閉時也不會提供任何反饋。可變通的,你可以啓動一個Activity作爲子Activity,它與父Activity有內在的聯繫。當子Activity關閉時,它會觸發父Activity中的一個事件處理函數。子Activity最適合用在一個Activity爲其它的Activity提供數據(例如用戶從一個列表中選擇一個項目)的場合。

    子Activity的創建和普通Activity的創建相同,也必須在應用程序的manifest中註冊。任何在manifest中註冊的Activity都可以用作子Activity。

啓動子Activity

    startActivityForResult方法和startActivity方法工作很相似,但有一個很重要的差異。Intent都是用來決定啓動哪個Activity,你還可以傳入一個請求碼。這個值將在後面用來作爲有返回值Activity的唯一ID。

下面的代碼顯示瞭如何啓動一個子Activity:

    private static final int SHOW_SUBACTIVITY = 1;

    Intent intent = new Intent(this, MyOtherActivity.class);

    startActivityForResult(intent, SHOW_SUBACTIVITY);

    和正常的Activity一樣,子Activity可以隱式或顯式啓動。下面的框架代碼使用一個隱式的Intent來啓動一個新的子Activity來挑選一個聯繫人:

    private static final int PICK_CONTACT_SUBACTIVITY = 2;

    Uri uri = Uri.parse(“content://contacts/people”);

    Intent intent = new Intent(Intent.ACTION_PICK, uri);

    startActivityForResult(intent, PICK_CONTACT_SUBACTIVITY);

返回值

當子Activity準備關閉時,在finish之前調用setResult來給調用的Activity返回一個結果。

setResult方法帶兩個參數:結果碼和表示爲Intent的負載值。結果碼是運行子Activity的結果,一般是Activity.RESULT_OK或Activity.RESULT_CANCELED。在一些情況下,你會希望使用自己的響應代號來處理特定的應用程序的選擇;setResult支持任何整數值。

作爲結果返回的Intent可以包含指向一個內容(例如聯繫人,電話號碼或媒體文件)的URI和一組用來返回額外信息的Extra。

接下來的代碼片段節選自子Activity的onCreate方法,顯示了怎樣向調用的Activity返回不同的結果:

   1: Button okButton = (Button) findViewById(R.id.ok_button);
   2:
   3: okButton.setOnClickListener(new View.OnClickListener() {
   4:
   5: public void onClick(View view)
   6:
   7: {
   8:
   9: Uri data = Uri.parse(“content://horses/” + selected_horse_id);
  10:
  11: Intent result = new Intent(null, data);
  12:
  13: result.putExtra(IS_INPUT_CORRECT, inputCorrect);
  14:
  15: result.putExtra(SELECTED_PISTOL, selectedPistol);
  16:
  17: setResult(RESULT_OK, result);
  18:
  19: finish();
  20:
  21: }
  22:
  23: });
  24:
  25: Button cancelButton = (Button) findViewById(R.id.cancel_button);
  26:
  27: cancelButton.setOnClickListener(new View.OnClickListener() {
  28:
  29: public void onClick(View view)
  30:
  31: {
  32:
  33: setResult(RESULT_CANCELED, null);
  34:
  35: finish();
  36:
  37: }
  38:
  39: });

處理子Activity的結果

    當子Activity關閉時,它的父Activity的onActivityResult事件處理函數被觸發。

重寫這個方法來處理從子Activity返回的結果。onActivityResult處理器接受好幾個參數:

請求碼

  曾經用來啓動子Activity的請求碼。

結果碼

    結果碼是由子Activity設置的,用來顯示它的結果。它可以是任何整數值,但典型的值是Activity.RESULT_OK和Activity.RESULT_CANCELLED。

如果子Activity非正常關閉或在關閉時沒有指定結果碼,結果碼都是Activity.RESULT_CANCELED。

數據

    一個Intent來打包任何返回的數據。依賴於子Activity的目的,它可能會包含一個代表特殊的從列表中選擇的數據的URI。可變通的,或額外的,子Activity可以使用“extras”機制以基礎值的方式返回臨時信息。

下面的框架代碼實現了一個Activity中的onActivityResult事件處理函數:

   1: private static final int SHOW_SUB_ACTIVITY_ONE = 1;
   2:
   3: private static final int SHOW_SUB_ACTIVITY_TWO = 2;
   4:
   5: @Override
   6:
   7: public void onActivityResult(int requestCode, int resultCode, Intent data) {
   8:
   9: super.onActivityResult(requestCode, resultCode, data);
  10:
  11: switch(requestCode)
  12:
  13: {
  14:
  15: case (SHOW_SUB_ACTIVITY_ONE) :
  16:
  17: {
  18:
  19: if (resultCode == Activity.RESULT_OK)
  20:
  21: {
  22:
  23: Uri horse = data.getData();
  24:
  25: boolean inputCorrect = data.getBooleanExtra(IS_INPUT_CORRECT, false);
  26:
  27: String selectedPistol = data.getStringExtra(SELECTED_PISTOL);
  28:
  29: }
  30:
  31: break;
  32:
  33: }
  34:
  35: case (SHOW_SUB_ACTIVITY_TWO) :
  36:
  37: {
  38:
  39: if (resultCode == Activity.RESULT_OK)
  40:
  41: {
  42:
  43: // TODO: Handle OK click.
  44:
  45: }
  46:
  47: break;
  48:
  49: }
  50:
  51: }
  52:
  53: }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章