標籤:
Android基礎之四大組件—Activity
- 1.什麼是Activity
- 2.Activity生命週期
- 3.Activity生命週期示範
- 4.Activity之間的通訊
- 5.Activity之載入模式
- 6.Activity的棧式管理
1.什麼是Activity?
Activity是使用者介面程式,它是Android應用程式的準系統單元,它的主要功能是提供介面。Activity是Android的核心類,該類的全名是android.app.Activity。Activity相當於C/S程式中的表單(From)或Web程式的頁面。每一個Activity提供一個可視化的地區。在這個地區可以放置各種Android組件,例如按鈕、映像、文字框等。
在Activity類中有一個oncreate事件方法,一般在該方法中對Acticity進行初始化。通過setContentView方法可以設定在Activity上顯示視圖組件。
一個帶介面的Android應用程式可以由一個或者多個Activity組成。至於這些Activity如何工作,它們之間的依賴關係,則完全取決於應用程式間的商務邏輯。
2.Activity生命週期
在Activity建立到摧毀的過程中需要在不同的階段調用7個生命週期方法。這七個生命週期的定義如下:
protected void onCreate(Bundle savedInstanceState) {} //在這裡建立介面,做一些資料的初始化工作; protected void onStart() {} //到這一步變成“使用者可見不可互動”的狀態; protected void onResume() {} //變成和使用者可互動的,(在Activity棧系統通過棧的方式管理這些Activity,即當前Activity在棧的最上端,運行完彈出棧,則回到上一個Activity); protected void onPause() {} //到這一步是可見但不可互動的,系統會停止動畫等消耗CPU的事情。從上文的描述已經知道,應該在這裡儲存你的一些資料,因為這個時候你的程式的優先順序降低,有可能被系統收回。在這裡儲存的資料,應該在onResume裡讀出來。 protected void onStop() {} //變得不可見 ,被下一個activity覆蓋了 protected void onRestart() {} protected void onDestroy() {} //activity被消滅
上面7個生命週期分別在4個階段按一定順序進行調用,
- 開始Activity:onCreate、onStart和onResume方法
- Activity失去焦點:onPause和onStop方法
- Activity重新獲得焦點:onRestart、onStart和onResume方法
關閉Activity:當Activity被關閉時系統會依次執行3個生命週期方法—onPause、onStop和onDestory方法
Activity的生命週期如所示
可以看出Activity包含兩層迴圈,第一層是onPause->onResume->onPause,第二層迴圈是onStop->onRestart->onStart->onResume->onPause->onStop。我們可以講兩層迴圈看成是整個Activity生命週期中的子生命週期。第一層成為焦點生命週期,第二層為可視生命週期。也就是說,第一層迴圈在Acitvity焦點的擷取與失去的過程中迴圈,這一過程中Activity是可見的。第二層迴圈實在Activity可見與不可見的過程中迴圈。
因此,Activity有如下三種生命週期:
整體生命週期:onCreate->……->onDestroy.
- 可視生命週期:onStart->……->onStop.
- 焦點生命週期:onResume->onPause.
3.生命週期示範
範例程式碼如下:
package com.hlh.activitydemo;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;public class MainActivity extends AppCompatActivity { private static String TAG = "MainActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.d(TAG, "onCreate: "); } @Override protected void onStart() { super.onStart(); Log.d(TAG, "onStart: "); } @Override protected void onResume() { super.onResume(); Log.d(TAG, "onResume: "); } @Override protected void onPause() { super.onPause(); Log.d(TAG, "onPause: "); } @Override protected void onStop() { super.onStop(); Log.d(TAG, "onStop: "); } @Override protected void onRestart() { super.onRestart(); Log.d(TAG, "onRestart: "); } @Override protected void onDestroy() { super.onDestroy(); Log.d(TAG, "onDestroy: "); }}
按如下步驟來操作應用程式:
(1)啟動應用程式
(2)按手機上的首頁按鈕進入主介面,然後重新進入應用程式介面
(3)關閉應用程式
按照上面步驟執行後,DDMS的Logcat列印的資訊如下:
從這個例子我們可以清晰看出Activity的整個生命週期的過程。
4.Activity之間的通訊
在 Android 中,不同的 Activity 執行個體可能運行在一個進程中,也可能運行在不同的進程中。因此我們需要一種特別的機制協助我們在 Activity 之間傳遞訊息。Android 中通過 Intent 對象來表示一條訊息,一個 Intent 對象不僅包含有這個訊息的目的地,還可以包含訊息的內容,這好比一封 Email,其中不僅應該包含收件地址,還可以包含具體的內容。對於一個 Intent 對象,訊息“目的地”是必須的,而內容則是可選項。
Intent負責對操作的動作、動作涉及資料、附加資料進行描述,Android則根據此Intent的描述,負責找到對應的組件,將 Intent傳遞給調用的組件,並完成組件的調用。因此,Intent在這裡起著一個媒體中介的作用,專門提供組件互相調用的相關資訊,實現調用者與被調用者之間的解耦。
通過下面執行個體我們可以很好的瞭解Activity之間的通訊,在主介面中點擊按鈕跳轉到另外一個activity,同時將資料傳遞給OtherActivity,綁定在TextView中。
MainActivity.java
public class MainActivity extends AppCompatActivity { private static String TAG = "MainActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button bt = (Button) findViewById(R.id.toOther); bt.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(MainActivity.this, OtherActivity.class); intent.putExtra("msg", "hello Activity"); startActivity(intent); } }); }}
OtherActivity.java
public class OtherActivity extends Activity{ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_other); TextView tv = (TextView) findViewById(R.id.tv); Intent intent = getIntent(); //設定文本 tv.setText(intent.getStringExtra("msg")); }}
note:建立立了一個Actvity後,必須在AndroidManifest.xml資訊清單檔中的標籤中註冊該actvity。
<activity android:name=".OtherActivity"/>
應用程式:
5.Activity之載入模式
Activity有四種載入模式(launchMode)。launchMode在多個Activity跳轉的過程中扮演著重要的角色,它可以決定是否產生新的Activity執行個體,是否重用已經存在的執行個體,是否和其他Activity共用一個task。簡單介紹一個task,task是一個具有棧結構的對象,一個task可以管理多個Activity,啟動一個應用,也就建立一個與之對應的task。
Activity的四種載入模式如下:
1.standard
2.singleTop
3.singleTask
4.singleInstance
我們可以在AndroidManifest.xml配置的Android:launchMode屬性為以上四種之一即可。
下面我們結合執行個體一一介紹這四種lanchMode:
1.standard
standard模式是預設的啟動方式,不用為配置android:launchMode屬性即可,當然也可以指定值為standard。我們建立一個Activity,命名為FirstActivity,來示範一下標準的啟動模式。FirstActivity代碼如下:
public class FirstActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_first); TextView textView = (TextView) findViewById(R.id.tv); textView.setText(this.toString()); Button button = (Button) findViewById(R.id.start); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(FirstActivity.this, FirstActivity.class); startActivity(intent); } }); }}
FirstActivity介面中的TextView用來顯示當前Activity執行個體的序號,Button跳轉到下一個介面
連續點擊幾個Button按鈕,將會出現下面現象:
我們發現都是FirstActivity執行個體但是序號不一樣,並且我們需要按兩次後退鍵才能返回到第一個 FirstActivity。每次跳轉系統都會在task中產生一個新的FirstActivity執行個體,並且將其放在棧頂,當我們按下back鍵時,才能看到原來的FirstActivity執行個體。
因此總結出standard啟動模式,不管有沒有已經存在的執行個體,都會產生一個新的執行個體。
2.singleTop
我們在上面的基礎上為指定屬性android:launchMode=”singleTop”,系統就會按照singleTop啟動模式處理跳轉行為。我們重複上面幾個動作,將會出現下面的現象:
我們看到這個跟standard的結果不同,三個序號都一樣,也就是說使用的是同一個FirstActivity執行個體。如果按back鍵,程式會立即退出。跳轉時系統會先在棧結構中尋找是否有一個FirstActivity執行個體正位於棧頂,如果有則不再產生新的,而是直接使用。也許有人會有疑問,我只看到棧內只有一個Activity,如果是多個Activity怎麼辦,如果不是在棧頂會如何?我們接下來再通過一個樣本來證實一下大家的疑問。
再建立一個Activity命名為SecondActivity,代碼如下:
public class SecondActivity extends Activity{ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); TextView tv = (TextView) findViewById(R.id.tv); tv.setText(this.toString()); Button button = (Button) findViewById(R.id.start); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(SecondActivity.this, FirstActivity.class); startActivity(intent); } }); }}
然後將之前的FirstActivity跳轉代碼改為:
Intent intent = new Intent(FirstActivity.this, SecondActivity.class); startActivity(intent);
示範結果如下:
我們看到,兩個FirstActivity的序號是不同的,證明從SecondActivity跳轉到FirstActivity時產生了新的FirstActivity執行個體。
我們看到,當從SecondActivity跳轉到FirstActivity時,系統發現存在有FirstActivity執行個體,但不是位於棧頂,於是重建一個執行個體。
這就是singleTop啟動模式,如果發現有對應的Activity執行個體正位於棧頂,則重複利用,不再產生新的執行個體。
3.singleTask
在上面的基礎上我們修改FirstActivity的屬性android:launchMode=”singleTask”。示範的結果如下:
我們注意到,在上面的過程中,FirstActivity的序號是不變的,SecondActivity的序號卻不是唯一的,說明從SecondActivity跳轉到FirstActivity時,沒有產生新的執行個體,但是從FirstActivity跳轉到SecondActivity時產生了新的執行個體。
在這個跳轉過程中系統發現有存在的FirstActivity執行個體,於是不再產生新的執行個體,而是根據棧先進後出的原則將FirstActivity之上的Activity執行個體統統出棧(如SecondActivity),將FirstActivity變為棧頂對象,顯示到幕前。如果將SecondActivity也設定為singleTask模式,那麼SecondActivity執行個體是不是可以唯一呢?在我們這個樣本中是不可能的,因為每次從SecondActivity跳轉到FirstActivity時,SecondActivity執行個體都被迫出棧,下次等FirstActivity跳轉到SecondActivity時,找不到存在的SecondActivity執行個體,於是必鬚生成新的執行個體。但是如果我們有ThirdActivity,讓SecondActivity和ThirdActivity互相跳轉,那麼SecondActivity執行個體就可以保證唯一。
這就是singleTask模式,如果發現有對應的Activity執行個體,則使此Activity執行個體之上的其他Activity執行個體統統出棧,使此Activity執行個體成為棧頂對象,顯示到幕前。
4.singleInstance
這種啟動模式比較特殊,因為它會啟用一個新的棧結構,將Acitvity放置於這個新的棧結構中,並保證不再有其他Activity執行個體進入。
我們修改FirstActivity的launchMode=”standard”,SecondActivity的launchMode=”singleInstance”,由於涉及到了多個棧結構,我們需要在每個Activity中顯示當前棧結構的id,所以我們為每個Activity添加如下代碼:
TextView textView = (TextView) findViewById(R.id.tv);textView.setText("current task id: " + this.getTaskId());
然後再示範一下這個流程:
我們發現這兩個Activity執行個體分別被放置在不同的棧結構中.可以發現從FirstActivity跳轉到SecondActivity時,重新啟用了一個新的棧結構,來放置SecondActivity執行個體,然後按下後退鍵,再次回到原始棧結構。
6.Activity的棧式管理
Android針對Activity的管理使用的是棧。你有可能不清楚什麼是棧,現在來解釋一下,棧是指資料項目按序排列的資料結構,只能在一端(稱為棧頂(top))對資料項目進行插入和刪除,一種先進後出的資料結構。而Android中是用task來存放Activity的。在第五小節簡單介紹了一下task。這裡詳細介紹一下
google官網對task的定義:
A task is a collection of activities that users interact with when performing a certain job. The activities are arranged in a stack (the back stack), in the order in which each activity is opened.
簡單來說task就是一組特定的activities集合,這些activities按照每一個被開啟的順序放到一個stack(棧)中。Activity棧可以由一個或者多個Task組成。
啟動一個應用時,系統會為之建立一個task來放置Activity,預設情況下,一個Activity啟動另外一個Activity時,兩個Activity放入同一個task中,後者被壓入前者所在的task棧中。當使用者按back鍵,後者從棧中彈出,前者又顯示在螢幕上。重點強調的是,啟動其他應用的Activity時,兩個Activity對使用者來說好像屬於同一個應用,其實這兩個Activity都建立了自己的task棧。系統中task和task之間是相互獨立的,當我們運行應用A時,按Home鍵回到主屏,啟動另外一個應用B,這時應用A的task被轉移到後台,剛啟動的應用B的task被轉移到前台,其棧頂Activity會顯示在螢幕上;再次按Home鍵回到開始啟動的應用A時,A應用的task任務棧又被轉移到前台,這時系統仍然保留task的所有Activity執行個體。
Android基礎之四大組件---Activity