- Android 5從入門到精通
- 李波
- 2730字
- 2021-03-19 15:29:00
3.2 Activity
Activity是Andorid組件中最基本也是最為常見(jiàn)的組件。Activity是用戶接口程序,原則上它會(huì)提供給用戶一個(gè)交互式的接口功能,幾乎所有的Activity都要和用戶打交道,也有人把它比喻成Android的管理員。需要在屏幕上顯示什么,用戶在屏幕上做什么,處理用戶不同操作等都由Activity來(lái)管理和調(diào)度。
Activity提供用戶與Android系統(tǒng)交互的接口,用戶通過(guò)Activity來(lái)完成自己的目的,例如打電話、拍照、發(fā)送E-mail、查看地圖等。每個(gè)Activity都提供一個(gè)用戶界面窗口,一般情況下,該界面窗口會(huì)填滿整個(gè)屏幕,但是也可以比屏幕小,或者浮在其他的窗口之上。
一個(gè)Android應(yīng)用程序通常由多個(gè)Activity組成,但是其中只有一個(gè)為主Activity,其作用相當(dāng)于Java應(yīng)用程序中的main函數(shù),當(dāng)應(yīng)用程序啟動(dòng)時(shí),作為應(yīng)用程序的入口首先呈現(xiàn)給用戶。Android應(yīng)用程序中的多個(gè)Activity直接可以相互調(diào)用以完成不同的工作。當(dāng)新的Activity被啟動(dòng)的時(shí)候,之前的Activity會(huì)被停止,但是不會(huì)被銷毀,而是被壓入到“后退棧(Back Stack)”的棧頂,而新啟動(dòng)的Activity獲得焦點(diǎn),顯示給用戶。“后退棧”遵循“后入先出”的原則。當(dāng)新啟動(dòng)的Activity被使用完畢,用戶單擊“Back”按鈕時(shí),當(dāng)前的Activity會(huì)被銷毀,而原先的Activity會(huì)被從“后退棧”的棧頂彈出并且激活。
當(dāng)Activity狀態(tài)發(fā)生改變時(shí),都會(huì)通過(guò)狀態(tài)回調(diào)函數(shù)通知Android系統(tǒng)。而程序編寫人員可以通過(guò)這些回調(diào)函數(shù)對(duì)Activity進(jìn)行進(jìn)一步的控制。
下面對(duì)Activity生命周期及其涉及的回調(diào)函數(shù)進(jìn)行簡(jiǎn)單介紹。
3.2.1 Activity的生命周期
從本質(zhì)上講,Activity在生命周期中共存在三個(gè)狀態(tài),分別為:
●運(yùn)行態(tài):運(yùn)行態(tài)指Activity運(yùn)行于屏幕的最上層并且獲得了用戶焦點(diǎn)。
●暫停態(tài):暫停態(tài)是指當(dāng)前Activity依然存在,但是沒(méi)有獲得用戶焦點(diǎn)。在其之上有其他的Activity處于運(yùn)行態(tài),但是由于處于運(yùn)行態(tài)的Activity沒(méi)有遮擋住整個(gè)屏幕,當(dāng)前Activity有一部分視圖可以被用戶看見(jiàn)。處于暫停態(tài)的Activity保留了自己所使用的內(nèi)存和用戶信息,但是在當(dāng)系統(tǒng)極度缺乏資源的情況下,有可能會(huì)被殺死以釋放資源。
●停止態(tài):停止態(tài)是指當(dāng)前Activity完全被處于運(yùn)行態(tài)的Activity遮擋住,其用戶界面完全不能被用戶看見(jiàn)。處于停止態(tài)的Activity依然存活,也保留了自己所使用的內(nèi)存和用戶信息,但是一旦系統(tǒng)缺乏資源,停止態(tài)的Activity就會(huì)被殺死以釋放資源。
Activity在聲明周期中從一種狀態(tài)到另一種狀態(tài)時(shí)會(huì)激發(fā)相應(yīng)的回調(diào)方法,這些回調(diào)方法包括:
●onCreate(Bundle savedInstanceState)。創(chuàng)建activity時(shí)調(diào)用。設(shè)置在該方法中,還以Bundle的形式提供對(duì)以前儲(chǔ)存的任何狀態(tài)的訪問(wèn)。其中參數(shù)savedInstanceState對(duì)象是用于保存Activity的對(duì)象的狀態(tài)。
●onStart()。activity變?yōu)樵谄聊簧蠈?duì)用戶可見(jiàn)時(shí)調(diào)用。
●onResume()。Activity開(kāi)始與用戶交互時(shí)調(diào)用(無(wú)論是啟動(dòng)還是重啟一個(gè)活動(dòng),該方法總是被調(diào)用的)。
●onPause()。當(dāng)Android系統(tǒng)要激活其他Activity時(shí),該方法被調(diào)用,暫停或收回CPU和其他資源時(shí)調(diào)用。
●onStop()。Activity被停止并轉(zhuǎn)為不可見(jiàn)階段時(shí)調(diào)用。
●onRestart()。重新啟動(dòng)已經(jīng)停止的Activity時(shí)調(diào)用。
●onDestroy()。Activity被完全從系統(tǒng)內(nèi)存中移除時(shí)調(diào)用,該方法被調(diào)用可能是因?yàn)橛腥酥苯诱{(diào)用finish()方法或者系統(tǒng)決定停止該活動(dòng)以釋放資源。
上面7個(gè)生命周期方法分別在4個(gè)階段按照一定的順序進(jìn)行調(diào)用,這4個(gè)階段如下:
●啟動(dòng)Activity。在這個(gè)階段依次執(zhí)行3個(gè)生命周期方法:onCreate、onStart和onResume。
●Activity失去焦點(diǎn)。如果在Activity獲得焦點(diǎn)的情況下進(jìn)入其他的Activity或應(yīng)用程序,這時(shí)當(dāng)前的Activity會(huì)失去焦點(diǎn)。在這一階段,會(huì)依次執(zhí)行onPause和onStop方法。
●Activity重獲焦點(diǎn)。如果Activity重新獲得焦點(diǎn),會(huì)依次執(zhí)行3個(gè)生命周期方法:onRestart、onStart和onResume。
●關(guān)閉Activity。當(dāng)Activity被關(guān)閉時(shí)系統(tǒng)會(huì)依次執(zhí)行3個(gè)生命周期方法:onPause、onStop和onDestroy。
Activity生命周期中方法調(diào)用過(guò)程如圖3.1所示。

圖3.1 Activity生命周期
通過(guò)圖3.1,可以很直觀了解到activity的整個(gè)生命過(guò)程。Activity的生命過(guò)程表現(xiàn)在三個(gè)層面,如圖3.2所示。

圖3.2 Activity的整個(gè)生命周期
通過(guò)圖3.2可以更清楚地了解Activity的運(yùn)行機(jī)制。如果Activity離開(kāi)了可見(jiàn)階段,長(zhǎng)時(shí)間失去了焦點(diǎn),Activity就很可能被系統(tǒng)銷毀以釋放資源。當(dāng)然,即使該Activity被銷毀掉,用戶對(duì)該Activity所做的更改也會(huì)被保存在Bundle對(duì)象中,當(dāng)用戶需要重新顯示該Activity時(shí),Android系統(tǒng)會(huì)根據(jù)之前保存的用戶更改信息將該Activity重建。
3.2.2 Activity的創(chuàng)建
在一個(gè)Android工程中,創(chuàng)建Activity的步驟如下:
步驟01 新建類。創(chuàng)建一個(gè)Activity,必須創(chuàng)建Android.app.Activity(或者它的一個(gè)已經(jīng)存在的子類)的一個(gè)子類,并重寫onCreate()方法。
步驟02 關(guān)聯(lián)布局xml文件。在新建的Activity中設(shè)置其布局方式,需要在res/layout目錄中新建一個(gè)xml布局文件,可以通過(guò)setContentView()來(lái)指定Activity的用戶界面的布局文件。
步驟03 注冊(cè)。在AndroidManifest.xml文件中對(duì)建立的Activity進(jìn)行注冊(cè),即在<application>標(biāo)簽下添加<activity>標(biāo)簽。例如,注冊(cè)ExampleActivity的代碼如下:
<application ...> <activity Android:name=".ExampleActivity" /> ... </application ...>
對(duì)于主Activity,要為其添加<intent-filter>標(biāo)簽。代碼如下:
<activity Android:name=".ExampleActivity" Android:icon="@drawable/app_icon"> <intent-filter> <action Android:name="Android.intent.action.MAIN" /> <category Android:name="Android.intent.category.LAUNCHER" /> </intent-filter> </activity>
其中<action Android:name="Android.intent.action.MAIN" />表示該Activity作為主Activity出現(xiàn),而<category Android:name="Android.intent.category.LAUNCHER" />表示該Activity會(huì)被顯示在最上層的啟動(dòng)列表中。
3.2.3 啟動(dòng)Activity
在Android系統(tǒng)中,除主Activity由系統(tǒng)啟動(dòng),其他Activity都要由應(yīng)用程序來(lái)啟動(dòng)。
(1)通常情況下,通過(guò)startActivity()方法來(lái)啟動(dòng)Activity,而要啟動(dòng)的Activity的信息由Intent對(duì)象來(lái)傳遞。例如:
Intent intent=new Intent(this, AnotherActivity.class); startActivity(intent);
表示通過(guò)當(dāng)前的Activity啟動(dòng)名為AnotherActivity的Activity。
有時(shí),用戶不需要知道要啟動(dòng)的Activity的名字,而可以僅制定要完成的行為,由Android系統(tǒng)來(lái)為用戶挑選合適的Activity。例如:
Intent intent=new Intent(Intent.ACTION_SEND); intent.putExtra(Intent.EXTRA_EMAIL, recipientArray); startActivity(intent);
其中Intent.EXTRA_EMAIL放置的是recipientArray中存儲(chǔ)的要發(fā)送的E-mail的目標(biāo)地址。該Intent對(duì)象被startActivity()啟動(dòng)后,Android系統(tǒng)會(huì)啟動(dòng)相應(yīng)的E-mail處理應(yīng)用程序,并將Intent.EXTRA_EMAIL中的內(nèi)容放置到郵件的目標(biāo)地址中。
(2)有時(shí),當(dāng)需要從啟動(dòng)的Activity獲取返回值的時(shí)候,需要使用startActivityForResult()方法代替startActivity()方法,并實(shí)現(xiàn)onActivityResult()方法來(lái)獲取返回值。
例如,在發(fā)送短信的時(shí)候,用戶需要從聯(lián)系人列表中獲取聯(lián)系人的信息,然后返回到短信發(fā)送界面。代碼如下:
Intent intent=new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI); startActivityForResult(intent, PICK_CONTACT_REQUEST);
當(dāng)用戶選擇了聯(lián)系人后,相關(guān)信息會(huì)被存儲(chǔ)到Intent對(duì)象中,并返回到onActivityResult()方法中。
3.2.4 關(guān)閉Activity
關(guān)閉Activity使用finish()方法。關(guān)閉之前啟動(dòng)的其他Activity可以使用finishActivity()方法。
需要注意的是,雖然Android SDK提供了關(guān)閉Activity的方法,但是通常情況下,程序員不應(yīng)該使用這些方法去強(qiáng)制關(guān)閉Activity。因?yàn)锳ndroid系統(tǒng)在為用戶維護(hù)Activity的生命周期,并且提供了完備的資源回收機(jī)制和資源重建機(jī)制,可以動(dòng)態(tài)地回收和重建Activity,因此Activity應(yīng)用交由Android系統(tǒng)來(lái)管理,除非已確定用戶不再需要當(dāng)前的Activity,并且不允許用戶回退到當(dāng)前Activity。
3.2.5 Activity數(shù)據(jù)傳遞
Activity數(shù)據(jù)傳遞共有三種:
●通過(guò)intent傳遞一些簡(jiǎn)單的數(shù)據(jù)。
●通過(guò)Bundle傳遞相對(duì)復(fù)雜的數(shù)據(jù)或者對(duì)象。
●通過(guò)startActivityForResult可以更方便地進(jìn)行來(lái)回的傳遞,當(dāng)然前兩種方法也可以來(lái)回傳遞。
假設(shè)由Activity1向Activity2傳遞數(shù)據(jù),利用三種方式實(shí)現(xiàn)的實(shí)例代碼如下。
(1)利用Intent傳遞數(shù)據(jù)。
在傳遞數(shù)據(jù)的Activity1中:
Intent intent=new Intent(Activity1.this,Activity2.class); intent.putExtra("author","leebo");//在Intent中加入鍵值對(duì)數(shù)據(jù),鍵為“author”,值為“l(fā)eebo” Activity1.this.startActivity(intent);
在取出數(shù)據(jù)的Activity2中:
Intent intent=getIntent();//獲得傳過(guò)來(lái)的Intent。 String value=intent.getStringExtra("author"); //根據(jù)鍵名author取出對(duì)應(yīng)鍵值為“l(fā)eebo”
(2)利用Bundle傳遞數(shù)據(jù)。
在傳遞數(shù)據(jù)的Activity1中:
Intent intent=new Intent(Activity1.this,Activity2.class); Bundle myBundle=new Bundle(); myBundle.putString("author","leebo"); intent.putExtras(myBundle); Activity1.this.startActivity(intent);
在取出數(shù)據(jù)的Activity2中:
Intent intent=getIntent(); Bundle myBundle=intent.getExtras(); String value=myBundle.getString("author"); //根據(jù)鍵名author取出對(duì)應(yīng)鍵值為“l(fā)eebo”
(3)利用startActivityForResult()傳遞數(shù)據(jù)。
startActivityForResult()方法不但可以把數(shù)據(jù)從Activity1傳遞給Activity2,還可以把數(shù)據(jù)從Activity2傳回給Activity1。
在Activity1中:
final int REQUEST_CODE=1; Intent intent=new Intent(Activity1.this,Activity2.class); Bundle mybundle=new Bundle(); mybundle.putString("author", "leebo");//把數(shù)據(jù)傳過(guò)去 intent.putExtras(mybundle); startActivityForResult(intent, REQUEST_CODE);
重載onActivityResult方法,用來(lái)接收傳過(guò)來(lái)的數(shù)據(jù)(接收b中傳過(guò)來(lái)的數(shù)據(jù)):
protected void onActivityResult(int requestCode, int resultCode,Intent intent){ if(requestCode==this.REQUEST_CODE){ switch(resultCode){ case RESULT_OK: Bundle b=intent.getExtras(); String str=b.getString("Result"); //獲取到Result中的值,為“from Activity2” break; default: break; } } }
在Activity2中:
Intent intent=getIntent(); Bundle myBundle=getIntent().getExtras(); String author=getBundle.getString("author"); Intent intent=new Intent(); Bundle bundle=new Bundle(); bundle.putString("Result","from Activity2"); intent.putExtras(bundle);
Activity02.this.setResult(RESULT_OK,intent);//通過(guò)intent將數(shù)據(jù)返回給Activity1,RESULT_ OK是結(jié)果碼:
finish();//結(jié)束當(dāng)前的Activity。
本質(zhì)上,這三種數(shù)據(jù)傳遞方式都是通過(guò)Intent來(lái)完成的。
- 軟件項(xiàng)目管理(第2版)
- 垃圾回收的算法與實(shí)現(xiàn)
- Visual FoxPro 程序設(shè)計(jì)
- Programming ArcGIS 10.1 with Python Cookbook
- 從0到1:HTML+CSS快速上手
- 名師講壇:Java微服務(wù)架構(gòu)實(shí)戰(zhàn)(SpringBoot+SpringCloud+Docker+RabbitMQ)
- TradeStation交易應(yīng)用實(shí)踐:量化方法構(gòu)建贏家策略(原書第2版)
- iOS開(kāi)發(fā)實(shí)戰(zhàn):從入門到上架App Store(第2版) (移動(dòng)開(kāi)發(fā)叢書)
- QGIS Python Programming Cookbook(Second Edition)
- Extending Unity with Editor Scripting
- Python數(shù)據(jù)科學(xué)實(shí)踐指南
- INSTANT EaselJS Starter
- Testing Practitioner Handbook
- C#開(kāi)發(fā)之道
- 數(shù)據(jù)庫(kù)基礎(chǔ)與應(yīng)用實(shí)驗(yàn)教程:Visual FoxPro 6.0