第六章:四大元件之Activity

自助者天助發表於2014-11-27

tivityActivity作為Android四大元件之一,也是其中最重要的一個元件。作為一個與使用者互動的元件,我們可以把Activity比較成為windows系統上的一個資料夾視窗,是一個與使用者互動的介面。再進一步說,當我們拿起Android開啟撥號功能,顯示出撥號盤的介面其實就是一個Activity;當然,可以更大範圍的說,手機螢幕上顯示的任何介面都是一個個Activity。

執行狀態:當Activity處於螢幕最前端,此時Actiivity完全顯示在使用者的介面中,並能獲取焦點時,可以響應使用者的的觸控螢幕等事件,此時為執行狀態。

暫停狀態:當Activity被其他Activity遮擋,但是仍然有部分可見,此時為暫停狀態;當處於暫停狀態時,Activity仍然會更新UI,但是此時不能獲取焦點,即不會響應使用者觸控、後退等事件。

停止狀態:當Activity被另外一個Activity完全遮擋,此時為停止狀態,停止狀態並不意味著Activity停止執行,而可以理解為轉入後臺執行。但是如果系統需要記憶體,會優先結束停止狀態的Activity釋放資源,所以在Activity轉入停止狀態時要對重要資料進行儲存。ctivity生命週期

    上圖就是Activity的生命週期圖,Activity的生命週期方法總共有七個。所謂生命週期,就是Activity在各個狀態轉變之間,系統會對其各個生命週期函式進行回撥,也就讓我們可以根據業務需求,重寫各個生命週期方法來實現軟體在各個狀態的業務邏輯。

啟動Activity到執行狀態:

  onCreate() -> onStart() -> onResume() -> 介面完全顯示

執行狀態到暫停狀態:

  介面完全顯示 -> onPause() -> 介面被部分遮蓋

暫停狀態到執行狀態:

  介面被部分遮蓋 -> onResume() -> 介面完全顯示

執行狀態到停止狀態:

  介面完全顯示 -> onPause() -> onStop() -> 介面完全遮蓋

停止狀態到執行狀態:

  介面完全遮蓋 -> onRestart() -> onStart() -> onResume() -> 介面完全顯示

退出Activity:

  介面完全顯示 -> onPause() -> onStop() -> 介面完全遮蓋 -> onDestroy() -> Activity結束生命週期

PS:當系統記憶體緊張時,系統可以將Activity釋放掉以獲取資源,優先釋放停止狀態的Activity,次之則是暫時狀態的Activity,而執行狀態的Acitivity一般不可能被強行釋放,除非極端缺乏資源(這時候直接當機得了。。。),當Activity被釋放時,直接轉入消亡,需要注意一點的是onDestroy()並不會被執行,所以把資料儲存放在onDestroy處理是不適當的,可以在onSaveInstanceState()中對重要資料進行相應的處理。

另外關於橫豎屏切割呼叫的生命週期如下:

橫屏->豎屏(呼叫一次生命週期)

  onPause() -> onStop() -> onDestroy() -> onCreate() -> onStart() -> onResume()

豎屏 -> 橫屏 (呼叫兩次生命週期)

如果不希望切換螢幕時呼叫生命週期方法,可以有如下方法:

1、不設定Activity的android:configChanges時,切屏會重新呼叫各個生命週期,切橫屏時會執行一次,切豎屏時會執行兩次

2、設定Activity的android:configChanges="orientation"時,切屏還是會重新呼叫各個生命週期,切橫、豎屏時只會執行一次

3、設定Activity的android:configChanges="orientation|keyboardHidden"時,切屏不會重新呼叫各個生命週期,只會執行onConfigurationChanged方法

Activity的啟動

  當我們希望從當前的Activity跳轉到下一個Activity時,我們就需要掌握Activity的啟動,參考下面程式碼:

複製程式碼
       Intent intent = new Intent(this, OtherActivity.class);//寫法1
       
//     Intent intent = new Intent(getApplicationContext(), OtherActivity.class);//寫法2
//       
//     Intent intent = new Intent();//寫法3
//     intent.setClass(this, OtherActivity.class);
       
       startActivity(intent);//啟動另外一個Activity
       
複製程式碼

   Intent是聯絡四大元件的紐帶,啟動一個Activity一般都是new一個Intent例項,同時指定相應的啟動元件,如OtherActivity.class。然後呼叫Activity的方法startActivity(intent)通知android系統載入OtherActivity。

Activity之間資料的傳遞

  對於應用來說,單純從一個Activity啟動另外一個Activity遠遠是不夠的,有時候需要比較的資料資訊交流。android系統提供了很多種資料通訊的方法,自然也為Activity之間的通訊提供了簡便的資料傳遞方法,參見下面程式碼:

FirstActivity向OtherActivity傳送資料<data,"傳遞的資料">

複製程式碼
1     Intent intent = new Intent(this, OtherActivity.class);
2         
3        intent.putExtra("data", "傳遞的資料");//data為key
4 //        另外一種方法,載入資料
5 //     Bundle bundle = new Bundle();
6 //     bundle.putString("data", "傳遞的資料");
7 //     intent.putExtras(bundle);
8         
9        startActivity(intent);
複製程式碼

有兩種表示的方法,一般第一種方法運用的場景是傳輸少量而且簡單的資料;後一種方法則是傳輸較多而比較複雜的資料所用。但是從底層上說,其實第一種方法是後一種方法的封裝,它仍然會在intent內部建立一個bundle並把資料(如例子中的“傳遞的資料”)放入其中。

OtherActivity獲取傳送的資料<data,"傳遞的資料">

1         Intent intent = getIntent();
2 //        獲取方法
3         String data = intent.getStringExtra("data");//data的值為“傳遞的資料”,由上個Activity傳入
4 //      另外一種方法
5 //      Bundle bundle = intent.getExtras();
6 //      String data = bundle.getString("data");

獲取的方法一般是先取得intent攜帶的bundle,然後通過get方法獲取儲存在其中的資料;而前面的方法並沒有明確獲取bundle的程式碼,因為intent.getStringExtra(key)在函式內部已經是先獲取好bundle並把相應key的資料解析出來了,所以兩種方法本質上來說是相同的,但是如果大量資料建議用後一種方法,因為從bundle中獲取資料比從intent中獲取資料效率有所提高,比較移動時代,效率是一個非常需要重視的東東。。

 FristActivity啟動OtherActivity並在其結束時獲取OtherActivity返回的資料

如果業務需要啟動另一個Activity後返回資料給原來的Activity,在啟動Activity是不是呼叫startActivity(intent),而是應該呼叫startActivityForResult(intent, requestCode),requestCode是一個給啟動的Activity的標識碼,是一個正整數的值,在有多個啟動的Activity時可以通過不同的標識碼來表示Activity返回的資料並進行不同的處理。在FristActivity中處理返回資料是在 onActivityResult(requestCode, resultCode, data)中處理,而第一個引數requestCode則是啟動時輸入的標識碼。參見程式碼

1  Intent intent = new Intent(this, OtherActivity.class);
2  startActivityForResult(intent, 0);//設定標識碼為0

這是啟動Activity的程式碼,但是我們要對於返回的資料,還需要在FristActivity中重寫onActivityResult(requestCode, resultCode, data)

複製程式碼
1 @Override
2 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
3   super.onActivityResult(requestCode, resultCode, data);
4   if(requestCode == 0){//根據requestCode的數值確實是哪個Activity返回的bundle
5     Bundle bundle = data.getExtras();
6     String getdata = bundle.getString("name");
7   }
8 } 
複製程式碼

然後在啟動的OtherActivity中重寫返回資料的方法

    Intent intent = new Intent();
    intent.putExtra("name", "返回的資料");
    setResult(1, intent);//設定需要返回資料的intent
    finish();//結束當前的activity    

一般setResult後需要呼叫finish()結束當前的Activity,此時才會將資料返回到FristActivity,資料返回也就是onActivityResult呼叫的時間在finish之前呼叫。

Activity的結束

finish():當執行finish()後系統會將該activity移出棧,但是並沒有馬上釋放資源,也不會呼叫onDestroy這個生命週期的方法。

onDestroy():當activity執行到這個生命週期時,也就意味著activity將會完全釋放,如果需要重新啟動這個activity,需要重新onCreate()。

System.exit(0):這個玩意會將整個Application給幹掉,退出程式。

相關文章