Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Activity詳解2

Activity詳解2

編輯:關於Android編程

首先,Activity是Android系統中的四大組件之一,可以用於顯示View。Activity是一個與用記交互的系統模塊,幾乎所有的 Activity都是和用戶進行交互的,但是如果這樣就能說Activity主要是用來顯示View就不太正確了。它不僅顯示數據,也傳輸數據,很多程序中使用到MVC模式,

M(Model 模型):Model是應用程序的主體部分,所有的業務邏輯都應該寫在這裡,在Android中Model層與JavaEE中的變化不大,如:對數據庫的操 作,對網絡等的操作都放在該層(但不是說它們都放在同一個包中,可以分開放,但它們統稱為Model層)。
V(View 視圖):是應用程序中負責生成用戶界面的部分,也是在整個MVC架構中用戶唯一可以看到的一層,接收用戶輸入,顯示處理結果;在Android應用中一般 采用XML文件裡德界面的描述,使用的時候可以非常方便的引入,當然也可以使用JavaScript+Html等方式作為View。
C(Controller控制層)android的控制層的重任就要落在眾多的activity的肩上了,所以在這裡就要建議大家不要在activity中寫太多的代碼,盡量能過activity交割Model業務邏輯層處理。

在Android中Activity主要是用來做控制的,它可以選擇要 顯示的View,也可以從View中獲取數據然後把數據傳給Model層進行處理,最後再來顯示出處理結果。

也有一種新的MVP模式:

 

模型(Model):負責處理數據的加載或者存儲,比如從網絡或本地數據庫獲取數據等;

  視圖(View):負責界面數據的展示,與用戶進行交互;

  主持人(Presenter):相當於協調者,是模型與視圖之間的橋梁,將模型與視圖分離開來。

其中的主要內容這裡不介紹,這裡告訴大家,不僅僅需要學習MVC模式,也需要學習MVP模式,這裡特別不建議大家這樣寫:將所有的事情都交給Activity來完成,比如網絡請求,業務邏輯處理,這樣造成了Activity特別臃腫,一個大的Activity,在後期很難維護。MVC如果用不好,就會將所有的信息都放在Activity上。

protected void onCreate(Bundle icicle);
protected void onStart();
protected void onRestart();
protected void onResume();
protected void onPause();
protected void onStop();
protected void onDestroy();

要想了解Activity,那麼就必須要清楚Activity的生命周期,圖片是最生動的,如下圖:

\

 

上面一張圖有可能有些模糊,那請看下面這張圖():

\

 



整個Activity周期,activity創建時調用Oncreate(),這個時候調用setContentView(View)函數,加載xml布局文件。調用OnStart()方法,Activity顯示在屏幕上,這個時候還不能與用戶交互,調用OnResume()方法,用戶與Activity進行交互,當前Activity被切換的時候,這個時候調用OnPause()方法,在該方法中保存一些持久數據和釋放占用的資源,這個時候,屏幕還是可見,調用onStop()方法,Activity切換到後台,用戶不可見。onDestroy()activity終止。


Activity的響應時間
當前Activity所在的線程為主線程,它的響應時間為5秒,如果在當前運行的Activity中進行耗時的操作且響應時間起過5秒,那麼程序就會報ANR錯誤。所以,這也是不建議在Activity中寫太多復雜代碼的原因之一。
當然,有些代碼只能寫在Activity中,不然就運行不了(它們不是生命周期方法),比如你想要獲得android系統或者硬件一的些信息,就必須在Activity中寫出來,如果單獨寫一個工具類獲得不了。

Activity棧
Activity棧保存了已經啟動並且還沒有終止的所有的Activity,並且我們知道棧是遵從“後進先出”的規則,那麼Activity棧同樣也遵從這樣的規則。

 

Activity 的狀態與其在Activity棧的位置有著密切的關系。不僅如此,Android系統在資源不足時,也是通過Activity棧來選擇哪些 Activity是可以被終止的,一般來講,Activity系統會優先選擇終止處於目前是停止狀態並且比較靠近Activity棧底的 Activity。

1. Activity的4種狀態

Activity的生命周期指Activity從啟動到銷毀的過程,Activity有4種狀態:

(1)活動(Active)狀態:這時候Activity處於棧頂,且是可見的,有焦點的,能夠接收用戶輸入前 景Activity。Runtime將試圖不惜一切代價保持它活著,甚至殺死其他Activity以確保它有它所需的資源。當另一個Activity變成Active時,當前 的將變成Paused狀態。

(2)暫停(Paused)狀態:在 某些情況下,你的Activity是可見的,但沒有焦 點,在這時候,Actvity處於Paused狀態。例如,如果有一個透明或非全屏幕上的Activity在你的Actvity上面,你的 Activity將。當處於Paused狀態時,該Actvity仍被認為是Active的,但是它不接受用戶輸入事件。在極端情況下,Runtime將 殺死Paused Activity,以進一步回收資源。當一個Actvity完全被遮住時,它將進入Stopped狀態。

(3)停止(Stopped)狀態:當Activity是不可見的時,Activity處於Stopped狀態。Activity將繼續保留在內存中保持當前的所有狀態和成員信息,假 設系統別的地方需要內存的話,這時它是被回收對象的主要候選。當Activity處於Stopped狀態時,一定要保存當前數據和當前的UI狀態,否則一 旦Activity退出或關閉時,當前的數據和UI狀態就丟失了。

(4)非活動(Inactive)狀態:Activity被殺掉以後或者被啟動以前,處於Inactive狀態。這時Activity已被移除從Activity堆棧中,需要重新啟動才可以顯示和使用。

 

一些調用實例

1) 啟動Activity:onCreate()->onStart()->onResume()->Activityis running

2) 按back鍵返回:onPause()->onStop()->onDestroy() 再次啟動時:onCreate()->onStart()->onResume()->Activityis running

3). 按home鍵返回:onPause()->onStop() 再次啟動時:onRestart()->onStart()->onResume()->Activity isrunning

4) 切換到別的Activity(當前Activity不finish),或者采用這個,啟動程序進入Activity,按Home鍵進入桌面,然後長按Home建點擊該應用重新進入Activity:onPause()->onStop() 再次啟動時:onRestart()->onStart()->onResume()->Activityis running

 

5) 切換到別的Activity(當前Activity finish):onPause()->onStop()->onDestroy() 再次啟動時:onCreate()->onStart()->onResume()->Activity isrunning

6)然後按掛機鍵,進入鎖屏界面,然後從鎖屏界面返回Activity:onPause()->onResume()

7)切換到另一個Activity對話框界面,然後按返回鍵返回原來的Activity:onPause()->onResume()

8)啟動本Activity中創建的對話框(彈出Toast和AlertDialog),按返回鍵從Dialog返回:Activity的狀態始終未變

9)無論現在是onPause狀態還是onStop狀態,當系統的內存不足時,都會將該Activity殺死,當再次進入該Activity重新創建。這意味著,如果發生這種情況,可能我們的onDestroy(如果在停止狀態被殺死),甚至是onStop都沒有得到執行(如果在暫停狀態被殺死),因此,一些重要的數據和狀態,需要在這種情況下也得到保存,Google為我們專門提供了一個回調函數,就是onSaveInstanceState(Bundle),通過該函數,可以將這些重要的數據在銷毀前進行保存,然後再onCreate時重新讀

10)橫豎屏切換時候activity的生命周期:

1、不設置Activity的android:configChanges時,切屏會重新調用各個生命周期,切橫屏時會執行一次,切豎屏時會執行兩次

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

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

11)當在MainActivity中按back鍵,退出時,或者在代碼中調用finish(),finishActivity()方法,最終就會走到onDestory()。

tips:

在多數情況下,你是不需要顯式地調用finish…()方法去銷毀一個activity。在將要討論到的activity生命周期裡,你可以知道,Android系統會為你管理activity的生命周期,所以你並不需要顯式銷毀activity(即調用finish類方法)。顯式地調用finish類方法,會對用戶的體驗產生不利的影響,除非你確實是不希望用戶返回到此activity(界面),才去顯式調用finish類方法。


特殊函數

 

1. startActivityForResult / onActivityResult / setResult 函數組合

提到這類函數組合,相信只要有過一段時間Android開發的來說都很熟悉了,此函數組合主要用於如下場景:用戶在A Activity上點擊某個按鈕,跳轉到B Activity,然後用戶在B Activity上進行一些具體的操作,待操作完成後返回到A Activity,同時常常將B Activity中操作的一些數據返回到A Activity中。

再如上場景中,A -> B 需要通過startActivityForResult()方式打開。具體方式如下:

1 button.setOnClickListener(new View.OnClickListener() {
2     @Override
3     public void onClick(View v) {
4         Intent intent = new Intent(AActivity.this, BActivity.class);
5         startActivityForResult(intent, 1);
6     }
7 });

其中,startActivityForResult第一個參數為Intent,因此,對於需要傳遞額外參數時,可以通過Intent直接傳遞。其中Bundle為可選參數。第二個參數為requestCode,即業務請求碼。

B Activity中,在處理完或相應完用戶操作後,自身結束前,需要通過setResult將數據回傳給A。

 1 btnClose.setOnClickListener(new View.OnClickListener() {
 2     public void onClick(View v) {
 3         
 4         // 需要返回的數據存入到intent中
 5         Intent intent = new Intent();
 6         intent.putExtra("name", "corn");
 7         
 8         //設置返回數據
 9         setResult(RESULT_OK, intent);
10         
11         //關閉Activity
12         finish();
13     }
14 });

接下來A接手B回傳的數據。

 1 @Override
 2 protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
 3     String name; 
 4     // 取得B回傳的數據
 5     if(resultCode == RESULT_OK ){
 6          name = intent.getStringExtra("name");
 7     } else if(resultCode == RESULT_CANCELED){
 8         // ...
 9     }
10 }

 

此函數組合中,需要注意如下問題:

1.根據項目的實際需要進行定義,特別需要注意的是,requestCode必須 >= 0,否則此類效果失效,其效果將變成startActivity()效果;

2.resultCode表示B中處理後的結果狀態,系統內部定義了RESULT_OK、RESULT_CANCELED和RESULT_FIRST_USER三種狀態。當然,自己可以定義成任何int型標識狀態。

3.有時在復雜的業務邏輯中,可能存在A startActivityForResult 到B,同時C也startActivityForResult 到B,且requestCode可能相同(以表示同意業務請求),這時可能需要在B中針對性的判斷此請求來源(來自於A還是C)。此時,可以通過intent傳參形式。相信大家都比較熟悉,其實Activity類中也提供了相應的函數可以獲取到來源Activity的類型函數:getCallingActivity()。但需要注意此函數僅針對startActivityForResult有效,返回的結果中包含完成包名。

4.A中回調函數調用時機需要注意,其調用發生在B的onPause之後,A的onRestart之前(如果B完成遮住了A),且必然在onResume之前。

5.此函數組合針對B的啟動模式為singleTask或singInstance將會失效。此時,onActivityResult將在A的onpause之後直接回調,且resultCode為RESULT_CANCELED。

 

2.moveTaskToBack

如《Android總結篇系列:Activity生命周期》一文中有提到的,模擬現在的主流應用最後按Back鍵時不是強制退出應用或直接結束根Activity,而是采取類Home鍵效果,此時可以直接通過此函數實現,非常實用。

1 @Override
2 public void onBackPressed() {
3     moveTaskToBack(true);
4 }

此方法直接將當前Activity所在的Task移到後台,同時保留activity順序和狀態。

 

3.onNewIntent調用時機

onNewIntent只有在以下場景才會回調:當前通過Intent方式啟動的Activity不是重新完整新建實例,而是復用之前已經存在的實例(如被設置了singleTop啟動模式,或FLAG_ACTIVITY_SINGLE_TOP intent flags或設置了Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP等,以此類推,被設置了singleTask或single。此時都會執行到onNewIntent)。onNewIntent調用後,將繼續回調onRestart,onResume...

 

4.onSaveInstanceState /onRestoreInstanceState調用時機

onSaveInstanceState調用時機:當Activity變得“容易”被系統銷毀時,onSaveInstanceState即被回調,除非該activity是被用戶主動銷毀的,例如當用戶按BACK鍵的時候。

注意上面的雙引號,何為“容易”?言下之意就是該activity還沒有被銷毀,而僅僅是一種可能性。這種可能性有哪些?

1.當用戶按下HOME鍵時;
2.長按HOME鍵,選擇運行其他的程序時;
3.按下電源按鍵(關閉屏幕顯示)時;
4.從activity A中啟動一個新的activity時;
5.屏幕方向切換時,例如從豎屏切換到橫屏時。

onRestoreInstanceState調用時機,activity A“確實”被系統銷毀了,而如果僅僅是停留在有這種可能性的情況下,則該方法不會被調用。另外,onRestoreInstanceState的bundle參數也會傳遞到onCreate方法中,也可以選擇在onCreate方法中做數據還原。

 1 @Override
 2     protected void onRestoreInstanceState(Bundle savedInstanceState) {
 4         super.onRestoreInstanceState(savedInstanceState);
 5         savedInstanceState.getString("name", "");
 7     }
 9     @Override
10     public void onSaveInstanceState(Bundle savedInstanceState) {
11         super.onSaveInstanceState(savedInstanceState);
12         savedInstanceState.putString("name", "corn");
13     }

或在onCreate中:

 1 public class AActivity extends ActionBarActivity {
 2 
 3     private String name;
 4 
 5     @Override
 6     protected void onCreate(Bundle savedInstanceState) {
 7         super.onCreate(savedInstanceState);
 8         setContentView(R.layout.a);
 9 
10         if (savedInstanceState != null) {
11             name = savedInstanceState.getString("name");
12         }
13 
14     }
15 
16 }

需要注意的是,onSaveInstanceState被調用時,其調用發生在Activity生命周期中具體的位置。以A->B為例,A中onSaveInstanceState調用發生在A:onPause -> B:onCreate -> B:onResume -> A:onSaveInstanceState -> A:onStop。

onSaveInstanceState常常用於存儲應用程序中當前Activity中重要的狀態數據,以免Activity被系統意外殺掉的情況下當用戶再次回來時不能找到之前的狀態。如同一個Activity中使用多個fragment實現菜單功能時,最好需要在此函數中記錄下當前菜單對應的fragment id等。


 

 

\ \
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved