日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
一步一步揭開Android應(yīng)用程序的神秘面紗

Android應(yīng)用程序是用Java語(yǔ)言寫的,通過aapt工具把應(yīng)用程序所需要的任何數(shù)據(jù)、資源文件打包成apk文件,這個(gè)文件是一個(gè)將應(yīng)用安裝到手機(jī)上的一個(gè)載體。

創(chuàng)新互聯(lián)服務(wù)項(xiàng)目包括桂東網(wǎng)站建設(shè)、桂東網(wǎng)站制作、桂東網(wǎng)頁(yè)制作以及桂東網(wǎng)絡(luò)營(yíng)銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢(shì)、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,桂東網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到桂東省份的部分城市,未來相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!

有很多方式,每個(gè)Android應(yīng)用程序存在于不同的世界:

(1)默認(rèn)的,每個(gè)應(yīng)用在他自己的Linux進(jìn)程中運(yùn)行,當(dāng)應(yīng)用中的任何代碼需要執(zhí)行時(shí)Android就啟動(dòng)相應(yīng)的進(jìn)程,當(dāng)不需要執(zhí)行時(shí)并且系統(tǒng)資源被其他應(yīng)用請(qǐng)求時(shí)android就關(guān)閉相應(yīng)的進(jìn)程。

(2)每個(gè)進(jìn)程都有他自己的虛擬機(jī)對(duì)象(VM),所以應(yīng)用程序代碼與其他的應(yīng)用運(yùn)行是彼此隔離的。

(3)默認(rèn)的,每個(gè)應(yīng)用被分配一個(gè)唯一的Linux user ID,都被設(shè)置權(quán)限以便應(yīng)用程序的文件只對(duì)用戶可見或者只對(duì)應(yīng)用自己可見。

安排兩個(gè)應(yīng)用程序共享一個(gè)user ID是可能的,這種情況下他們彼此之間是可以看見對(duì)方的文件的,為了保護(hù)系統(tǒng)資源,擁有相同ID的應(yīng)用也能被安排運(yùn)行在一個(gè)相同的Linux進(jìn)程中,共享相同的VM。

1、應(yīng)用組件(Application Components)

Android一個(gè)核心的特點(diǎn)就是一個(gè)應(yīng)用能使用另一個(gè)應(yīng)用的元素(如果另一個(gè)應(yīng)用允許的話),你的應(yīng)用不需要包含你用到的另一個(gè)應(yīng)用的代碼也不需要你連接這些代碼,相反的,只是當(dāng)應(yīng)用需要這些代碼時(shí),就啟動(dòng)另一個(gè)應(yīng)用相應(yīng)的代碼(不是讓另一個(gè)應(yīng)用全部啟動(dòng))

為了這個(gè)能工作,當(dāng)一個(gè)應(yīng)用的任何部分被需要時(shí)系統(tǒng)必須能啟動(dòng)這個(gè)應(yīng)用進(jìn)程,并且將這個(gè)部分實(shí)例化成java對(duì)象,因此,和其他大多數(shù)系統(tǒng)不同的是,android應(yīng)用程序沒有一個(gè)單獨(dú)的程序入口(例如:沒有main()函數(shù)),相反的,android應(yīng)用有必要的組件以便當(dāng)需要時(shí)系統(tǒng)能實(shí)例化并運(yùn)行它,android中有四種組件:

(1)Activity

一個(gè)Activity是一個(gè)可見的用戶可以使用的用戶界面,如果一個(gè)應(yīng)用中有多個(gè)Activity,雖然彼此結(jié)合形成一個(gè)應(yīng)用在一起工作,但是每個(gè)Activity是彼此獨(dú)立的,每個(gè)都是Activity的一個(gè)子類。

一個(gè)應(yīng)用程序可能由一個(gè)或多個(gè)Activity組成,這些Activity這么樣顯示,需要多少個(gè)Activity,依賴于這個(gè)應(yīng)用的設(shè)計(jì)者,一般的,有一個(gè)Activity應(yīng)該被標(biāo)記成當(dāng)這個(gè)應(yīng)用啟動(dòng)時(shí)第一個(gè)呈現(xiàn)出來給用戶的。

每個(gè)Activity默認(rèn)的被給予一個(gè)窗口來繪制,一般的,這個(gè)窗口占滿整個(gè)屏幕,但是他可以比屏幕小并且浮在另一個(gè)窗口的上面。

一個(gè)窗口中的可見的內(nèi)容是由一些具有層次關(guān)系的view組成的,都是繼承自View類的,每個(gè)view都控制一個(gè)窗口中的特定的矩形框,parent view 包含children view和組織children view的布局,leaf view(那些在繼承層次最底層的view)繪制在他們所控制的矩形框中,并且對(duì)用戶的動(dòng)作做出直接的回應(yīng),因此view就是Activity和用戶交互的地方,android有很多已經(jīng)做好的view你可以使用,包括buttons,text fields,scroll bars,menu items,check boxes等等

一個(gè)view hierarchy是通過Activity.setContentView()方法被放到一個(gè)Activity的window中的,content view是view hierarchy中最頂端的那個(gè)view。

(2)Services

一個(gè)service不是一個(gè)用戶可見的組件,在不確定的一段時(shí)間內(nèi)運(yùn)行在后臺(tái),每個(gè)service都繼承自Service類。

你可以連接(connect)或者綁定(bind)到一個(gè)正在運(yùn)行的service(如果這個(gè)service還沒運(yùn)行的話就啟動(dòng)它),當(dāng)連接到service后,你可以通過一個(gè)service暴露出來的接口和這個(gè)service交流,對(duì)music service來說,這個(gè)接口可以是允許用戶暫停,后退,停止,重新播放。

和Activity或者其他組件一樣,service運(yùn)行在這個(gè)應(yīng)用進(jìn)程的主線程中,所以他不會(huì)阻塞其他的組件或者用戶界面,他們經(jīng)常為那些耗時(shí)長(zhǎng)的任務(wù)單獨(dú)開一個(gè)線程。

(3)Broadcast receivers

一個(gè)broadcast receiver這樣一個(gè)組件,他只是接收廣播并作出反應(yīng),在系統(tǒng)中有很多已有的廣播,比如反應(yīng)時(shí)區(qū)變化(timezone)的,電池變化(battery)的,用戶修改了系統(tǒng)語(yǔ)言時(shí)的廣播,應(yīng)用程序也可以自己定義廣播,比如定義這樣一個(gè)廣播,讓其他的應(yīng)用知道某些數(shù)據(jù)已經(jīng)下載完畢了可以使用了。

一個(gè)應(yīng)用可以有任意多個(gè)broadcast receiver來對(duì)他所關(guān)心的廣播進(jìn)行監(jiān)聽并作出反應(yīng)。所有的receiver都繼承自BroadcastReceiver類。

BroadcastReceiver不顯示在用戶界面上,然而,他們可以啟動(dòng)一個(gè)Activity來作為他們接收到的信息一種反應(yīng),或者他們可以使用NotificationManager來提示用戶,Notifications可以通過不同的方式獲得用戶的注意,比如點(diǎn)亮呼吸燈,震動(dòng)電話,播放一個(gè)聲音等等,他們一般放一個(gè)圖標(biāo)在狀態(tài)欄上,來讓用戶可以打開獲得這些信息。

(4)Content providers

Content providers是一個(gè)應(yīng)用程序數(shù)據(jù)的集合,來讓其他的應(yīng)用可以訪問這些數(shù)據(jù),這些數(shù)據(jù)可以被存在文件系統(tǒng)中,SQLite數(shù)據(jù)庫(kù)中,或者其他可以存數(shù)據(jù)的地方,Content providers是一個(gè)基本的方法集合來使其他的應(yīng)用可以獲得和存儲(chǔ)這些數(shù)據(jù),然而應(yīng)用不直接調(diào)用這些方法,而是使用一個(gè)ContentResolver對(duì)象來調(diào)用這些方法,一個(gè)ContentResolver可以和任何的Content providers交流,他和provider協(xié)作來管理系統(tǒng)中任何進(jìn)程間的通信。

無論何時(shí)一個(gè)請(qǐng)求都應(yīng)該由一個(gè)特定的組件來處理,android系統(tǒng)來確保包含這個(gè)組件的應(yīng)用進(jìn)程運(yùn)行,如果需要就啟動(dòng)它,如果需要就為這個(gè)組件創(chuàng)造一個(gè)實(shí)例,確保這個(gè)組件的一個(gè)適當(dāng)?shù)膶?shí)例可以被得到。

2、啟動(dòng)組件:intent

當(dāng)有一個(gè)來自于content resolver的請(qǐng)求指向Content provider時(shí),content provider啟動(dòng),其他的三個(gè)組件(Activity,service,broadcast receiver)是通過一個(gè)叫做intent的異步的消息來啟動(dòng)的,一個(gè)intent持有一個(gè)message的內(nèi)容,對(duì)Activity和service來說,他是一個(gè)被要求的動(dòng)作(action)和在該動(dòng)作上的數(shù)據(jù)的URI,對(duì)broadcast receiver來說,intent對(duì)象是一個(gè)被廣播的動(dòng)作。

針對(duì)每種組件分別有對(duì)應(yīng)的方法來啟動(dòng)它:

(1)一個(gè)Activity是通過傳遞一個(gè)Intent對(duì)象到Context.startActivity()或者Activity.startActivityForResult()來啟動(dòng)的(或者去做一些新的任務(wù)),被啟動(dòng)的這個(gè)Activity可以通過getIntent()來獲得導(dǎo)致他啟動(dòng)的那個(gè)intent的。

(2)一個(gè)service是通過傳遞一個(gè)Intent對(duì)象到Context.startService()來啟動(dòng)的(或者給一些新的命令給正在運(yùn)行的service),android調(diào)用service的onStart()方法,并且把Intent對(duì)象傳遞給他,同樣的,一個(gè)Intent可以傳遞到Context.bindService()方法里來建立一個(gè)介于正在運(yùn)行的service和調(diào)用他的組件之間的連接,這個(gè)service通過onBind()方法來接收這個(gè)Intent對(duì)象,(如果這個(gè)service還沒有運(yùn)行,bindservice()能選擇性的啟動(dòng)它),在后面的部分,關(guān)于綁定service的更多詳細(xì)的信息請(qǐng)查看遠(yuǎn)程調(diào)用。

(3)一個(gè)應(yīng)用可以通過傳遞一個(gè)Intent對(duì)象給像Context.sendBroadcast(), Context.sendOrderedBroadcast(), Context.sendStickyBroadcast()這樣的方法來開始一個(gè)廣播,android通過調(diào)用對(duì)應(yīng)的onReceive()方法將intent傳遞給所有對(duì)這個(gè)廣播感興趣的broadcast receiver。

3、關(guān)閉組件(Shutting down components)

當(dāng)對(duì)來自于content resolver的請(qǐng)求作出回應(yīng)時(shí)content provider就啟動(dòng)了,當(dāng)有一個(gè)感興趣的broadcast message被廣播時(shí),broadcast receiver啟動(dòng),所以我們需要知道怎么關(guān)閉這些組件。

(1)Activity可以通過調(diào)用它自己的finish()方法來關(guān)閉,一個(gè)Activity也可以通過調(diào)用finishActivity()來關(guān)閉另一個(gè)Activity(這個(gè)Activity是通過調(diào)用startActivityForResult()來啟動(dòng)的)。

(2)一個(gè)service可以通過調(diào)用自己的stopSelf(),或者Context.stopService()來關(guān)閉。

當(dāng)組件不再使用時(shí)或者android為了更多組件能運(yùn)行而回收內(nèi)存時(shí),android系統(tǒng)是關(guān)閉這些組件的,在后面的部分,可以在組件的生命周期中看到更多更詳細(xì)的介紹。

4、Activities and Tasks

一個(gè)Activity可以啟動(dòng)另一個(gè)Activity,即使這個(gè)Activity是定義在另一個(gè)應(yīng)用里的,比如說,你想展示給用戶一條街的地圖,現(xiàn)在已經(jīng)有一個(gè)Activity可以做這件事,那么現(xiàn)在你需要做的就是將你請(qǐng)求的信息放進(jìn)一個(gè)Intent對(duì)象里,并且通過startActivity()傳遞給他,這個(gè)地圖就可以顯示出來了,但用戶按下BACK鍵時(shí),你的Activity又重新出現(xiàn)在屏幕上。

對(duì)用戶來說,顯示地圖的Activity和你的Activity好像在一個(gè)應(yīng)用中的,即使是他們是定義在不用的應(yīng)用中的,運(yùn)行在各自的應(yīng)用進(jìn)程中,android將兩個(gè)Activity放進(jìn)一個(gè)task里,一個(gè)task是一組彼此聯(lián)系的Activity,被安排在一個(gè)堆棧中,堆棧中的根Activity就是開辟這個(gè)task的,一般的,他是用戶選擇應(yīng)用后首先啟動(dòng)的那個(gè)Activity,堆棧頂部的Activity是當(dāng)前正在運(yùn)行的Activity,當(dāng)一個(gè)Activity啟動(dòng)另一個(gè)Activity時(shí),新的Activity被壓進(jìn)堆棧中,成為運(yùn)行的Activity,當(dāng)用戶按下BACK鍵,當(dāng)前的Activity彈出堆棧,先前的Activity恢復(fù)成為運(yùn)行的Activity。

一個(gè)task就是一組Activity的堆棧,不是在manifest文件里的一個(gè)類,一個(gè)元素,所以沒有方法來為一個(gè)task里的Activity獨(dú)立的設(shè)置值,對(duì)task設(shè)置值是在root Activity里設(shè)置的。

一個(gè)task里的所有Activity組成一個(gè)單元,整個(gè)task(整個(gè)Activity堆棧)可以在前臺(tái),也可以在后臺(tái)(應(yīng)用程序的切換就是task的前后臺(tái)的切換),假設(shè),當(dāng)前的task有四個(gè)Activity在堆棧里,用戶按下HOME鍵,去開啟另一個(gè)應(yīng)用(實(shí)際上是一個(gè)新的task),那么當(dāng)前的task就退到后臺(tái)運(yùn)行,新開啟的應(yīng)用的root Activity此時(shí)就顯示出來了,然后,過了一段時(shí)間,用戶回到主界面,又重新選擇了以前的那個(gè)應(yīng)用(先前的那個(gè)task),那么先前的那個(gè)task此時(shí)又回到了前臺(tái)了,當(dāng)用戶按下BACK鍵時(shí),屏幕不是顯示剛剛關(guān)閉的那個(gè)應(yīng)用,而是移除回到前臺(tái)的這個(gè)task堆棧棧頂Activity,將下一個(gè)Activity顯示出來。

剛才描述的情況是Activity和task默認(rèn)的行為,但是有很多的方法來對(duì)幾乎所有的方面進(jìn)行修改,如Activity和task的聯(lián)系。task里Activity的行為,是受啟動(dòng)它的Intent對(duì)象的flag和在manifest文件中的Activity的屬性集合共同影響的。

Flag:

FLAG_ACTIVITY_NEW_TASK

FLAG_ACTIVITY_CLEAR_TOP

FLAG_ACTIVITY_RESET_TASK_IF_NEEDED

FLAG_ACTIVITY_SINGLE_TOP

屬性:

taskAffinity

launchMode

allowTaskReparenting

clearTaskOnLaunch

alwaysRetainTaskState

finishOnTaskLaunch

5、Affinities and new tasks

默認(rèn)的,一個(gè)應(yīng)用里的所有Activity都有聯(lián)系,所有都是屬于一個(gè)task的,然而,可以通過 下的taskAffinity屬性來為每個(gè)Activity單獨(dú)的設(shè)置屬性關(guān)系,定義在不同應(yīng)用中的Activity可以共享一種關(guān)系(affinity),或者定義在同一個(gè)應(yīng)用中的Activity可以分配不同的關(guān)系(affinity)。這種關(guān)系在兩種情況下生效,當(dāng)啟動(dòng)Activity的 Intent對(duì)象包含有FLAG_ACTIVITY_NEW_TASK標(biāo)志,一個(gè)Activity的allowTaskReparenting屬性設(shè)置為true。

FLAG_ACTIVITY_NEW_TASK

一個(gè)Activity調(diào)用startActivity()啟動(dòng)一個(gè)新的Activity時(shí),新的Activity會(huì)壓入到相同的task中的,如果傳遞給startactivity()的Intent對(duì)象含有FLAG_ACTIVITY_NEW_TASK標(biāo)志,系統(tǒng)就會(huì)尋找一個(gè)新的task來裝這個(gè)新的Activity,然而,也不總是這么做,如果已經(jīng)有一個(gè)task和這個(gè)新的的Activity有相同的關(guān)系,那么就把這個(gè)新的Activity放進(jìn)這個(gè)task里,如果沒有,就啟動(dòng)一個(gè)新的task。

allowTaskReparenting屬性

如果一個(gè)Activity的allowTaskReparenting屬性設(shè)置為true,這個(gè)Activity就可以從啟動(dòng)時(shí)的那個(gè)task移動(dòng)到一個(gè)和他有關(guān)系的當(dāng)前在前臺(tái)的一個(gè)task里,比如,假設(shè)現(xiàn)在有一個(gè)天氣預(yù)報(bào)的Activity被定義在一個(gè)旅行的應(yīng)用里,他和這個(gè)應(yīng)用里的其他Activity有相同的關(guān)系(默認(rèn)的關(guān)系),并且他允許reparenting,現(xiàn)在你自己應(yīng)用有一個(gè)Activity啟動(dòng)這個(gè)天氣預(yù)報(bào)的Activity,那么天氣預(yù)報(bào)Activity就會(huì)移動(dòng)到你的Activity所在的task里,當(dāng)旅行的應(yīng)用又回到前臺(tái)時(shí),天氣預(yù)報(bào)Activity重新回到以前的那個(gè)task并顯示。(個(gè)人觀點(diǎn):如果說沒有設(shè)置這個(gè)屬性,或者這個(gè)屬性設(shè)置為false,那么一個(gè)應(yīng)用里的Activity調(diào)用另一個(gè)應(yīng)用里的Activity時(shí),系統(tǒng)是為另一個(gè)應(yīng)用里的Activity創(chuàng)建一個(gè)實(shí)例,然后放到同一個(gè)task里,但是如果設(shè)置了allowTaskReparenting為true,那么另一個(gè)應(yīng)用里的Activity是可以在不同的task間來回移動(dòng)的,那個(gè)task在前臺(tái)就移動(dòng)到那個(gè)task里)

6、啟動(dòng)方式

下的launchMode屬性可以設(shè)置四種啟動(dòng)方式:

"standard" (the default mode)

"singleTop"

"singleTask"

"singleInstance"

這些不同的方式可以從下面的四點(diǎn)來說:

(1)對(duì)一個(gè)Intent作出回應(yīng)時(shí)哪個(gè)task應(yīng)該去持有這個(gè)Activity。

對(duì)standard和singleTop方式來說,新的Activity和通過startActivity調(diào)用他的Activity處在同一個(gè)task中,如果調(diào)用時(shí)Intent對(duì)象里含有FLAG_ACTIVITY_NEW_TASK標(biāo)志,那么就像前面講的那樣的尋找一個(gè)新的task。

相反的,singTask和singleInstance方式,總是標(biāo)志Activity為task的root Activity,他們不會(huì)進(jìn)入到其他的task中。

(2)一個(gè)Activity是否可以有多個(gè)實(shí)例。

一個(gè)standard或者singleTop屬性的Activity可以實(shí)例化多次,他們可以屬于多個(gè)不同的task。

相反的,singleTask或者singleInstance屬性的Activity只能有一個(gè)實(shí)例(單例)。

(3)實(shí)例是否能允許在task里有其他的Activity。

一個(gè)singleInstance屬性的Activity單獨(dú)的在他自己的task里,并且這個(gè)task里只能有他自己一個(gè)Activity,如果他啟動(dòng)了另一個(gè)Activity,那個(gè)Activity會(huì)根據(jù)啟動(dòng)模式來啟動(dòng)并裝進(jìn)一個(gè)不同的task里。其他的方面,singleInstance和singleTask一樣的。

其他三個(gè)方式允許有多個(gè)Activity在一個(gè)task里,一個(gè)singleTask屬性的Activity總是一個(gè)task里的root Activity,但是他可以啟動(dòng)另外的Activity并且將這個(gè)新的Activity裝進(jìn)同一個(gè)task里,standard和singleTop屬性的Activity可以出現(xiàn)在task的任何地方。

(4)一個(gè)類(Activity)的對(duì)象是否可以被啟動(dòng)來處理一個(gè)新的Intent。

對(duì)默認(rèn)的standard方式,會(huì)實(shí)例化一個(gè)對(duì)象來處理每一個(gè)新的Intent,每個(gè)實(shí)例處理一個(gè)新的Intent,對(duì)singleTop方式,如果一個(gè)已經(jīng)存在的實(shí)例是在task的棧頂,那么就重用這個(gè)實(shí)例來處理這個(gè)新的Intent,如果這個(gè)實(shí)例不在棧頂,那就不復(fù)用他,而是重新創(chuàng)建一個(gè)實(shí)例來處理這個(gè)新的Intent并且將這個(gè)實(shí)例壓入堆棧。

例如現(xiàn)在有一個(gè)task堆棧ABCD,A是root Activity,D是棧頂Activity,現(xiàn)在有一個(gè)啟動(dòng)D的Intent來了,如果D是默認(rèn)的standard方法,那么就會(huì)創(chuàng)建一個(gè)新的實(shí)例來處理這個(gè)Intent,所以這個(gè)堆棧就變?yōu)锳BCDD,然而如果D是singleTop方式,這個(gè)已經(jīng)存在的棧頂?shù)腄就會(huì)來處理這個(gè)Intent,所以堆棧還是ABCD。D此時(shí)調(diào)用onNewIntent(),此時(shí)D可以調(diào)用getIntent()來獲得最初的Intent,或者調(diào)用setIntent()來更新這個(gè)Intent。

如果現(xiàn)在有一個(gè)Intent來啟動(dòng)B,不管B是standard還是singleTop(因?yàn)楝F(xiàn)在B不在棧頂),都會(huì)創(chuàng)建一個(gè)新的實(shí)例,所以堆棧變?yōu)锳BCDB

在一個(gè)task里,對(duì)singleTask和singleInstance屬性的Activity只能有一個(gè)實(shí)例。所以這僅有的一個(gè)會(huì)來處理所以的Intent,一個(gè)singleInstance屬性Activity總在棧頂(因?yàn)閠ask里就只有他一個(gè)Activity),所以他會(huì)處理所以的Intent,但是一個(gè)singleTask屬性的Activity必須是task的root Activity(也就是必須在棧底),不能確定他的上面是否還有其他的Activity,如果沒有,就可以處理,如果還有其他的Activity,那么如果現(xiàn)在有一個(gè)Intent來啟動(dòng)這個(gè)singleTask屬性的Activity,這個(gè)Intent將會(huì)被丟掉(即使是這個(gè)Intent被丟掉,他的到來還是會(huì)導(dǎo)致這個(gè)task回到前臺(tái))。

當(dāng)創(chuàng)建一個(gè)類(Activity)的實(shí)例來處理一個(gè)新的Intent時(shí),用戶可以按下BACK鍵回到上一個(gè)Activity,但是如果是用已經(jīng)存在的棧頂?shù)腁ctivity來處理Intent的話,按下BACK鍵是不能回到以前的狀態(tài)的(沒處理這個(gè)Intent之前)。

7、清理堆棧

當(dāng)用戶離開一個(gè)task一段時(shí)間后,系統(tǒng)就會(huì)清理掉task里出了rootActivity以外的Activity,如果用戶又回來了,顯示的是rootActivity,就像是用戶離開又回來,是放棄以前的東西,開始新的東西。

上面說的是默認(rèn)的情況,有一些Activity的屬性可以用來控制和修改這些行為。

alwaysRetainTaskState

如果一個(gè)task里的root Activity的alwaysRetainTaskState屬性設(shè)置為true,那么前面描述的默認(rèn)情況就不會(huì)出現(xiàn)了,task即使過了一段時(shí)間也會(huì)一直保留所有的Activity。

clearTaskOnLaunch

如果一個(gè)task里的root Activity的clearTaskOnLaunch屬性設(shè)置為true,和alwaysRetainTaskState相反,即使是一瞬間的離開,系統(tǒng)馬上就會(huì)清理掉task里出rootActivity以外的所有Activity。

finishOnTaskLaunch

這個(gè)屬性和clearTaskOnLaunch一樣,但是他是對(duì)一個(gè)Activity起作用,不是整個(gè)task,他能引起所有的Activity離開,包括root Activity,當(dāng)這個(gè)屬性設(shè)置為true,只是當(dāng)用戶使用這個(gè)應(yīng)用時(shí)Activity才在task里,一旦用戶離開后重新回來,顯示的不是當(dāng)前的界面。

還有其他的方法來從task里強(qiáng)制移動(dòng)Activity,如果一個(gè)Intent對(duì)象里包含F(xiàn)LAG_ACTIVITY_CLEAR_TOP標(biāo)志,并且目標(biāo)task里已經(jīng)一個(gè)在自己task里可以處理Intent的Activity(就是處理這個(gè)Intent無需實(shí)例化另外一個(gè)Activity),那么在這個(gè)Activity之上的所有Activity將被清除,能處理這個(gè)Intent的Activity就移到棧頂來處理這個(gè)Intent,例如ABCD堆棧,含有FLAG_ACTIVITY_CLEAR_TOP標(biāo)志的Intent來啟動(dòng)B,那么清除CD,B到達(dá)棧頂來響應(yīng)Intent,此時(shí)是AB,如果B設(shè)置了standard屬性,那么還是清楚CD,然后再創(chuàng)建一個(gè)實(shí)例來響應(yīng)Intent,此時(shí)是ABB,因?yàn)閟tandard屬性的Activity總是創(chuàng)建一個(gè)新的實(shí)例來響應(yīng)新的Intent。

8、進(jìn)程和線程(Processes and Threads)

當(dāng)一個(gè)應(yīng)用的第一個(gè)組件需要運(yùn)行時(shí),android系統(tǒng)就為這個(gè)組件啟動(dòng)一個(gè)只有一個(gè)線程的Linux進(jìn)程,默認(rèn)的,應(yīng)用的所有組件都運(yùn)行這個(gè)進(jìn)程中的這個(gè)線程中。

但是,你可以安排組件運(yùn)行在其他的進(jìn)程中,并且為你的任意的進(jìn)程增加若干線程。

1、 進(jìn)程

組件運(yùn)行的進(jìn)程是在manifest文件里控制的,四大組件都一個(gè)process屬性可以指定進(jìn)程來運(yùn)行,這些屬性可以被設(shè)置為了每個(gè)組件都可以運(yùn)行在他自己的進(jìn)程中,或者幾個(gè)組件共享一個(gè)進(jìn)程,或者不共享,如果兩個(gè)應(yīng)用共享一個(gè)Linux user ID并且有相同的權(quán)限,那么就可以使這兩個(gè)應(yīng)用中的組件運(yùn)行在相同的進(jìn)程中, 也有process屬性,用來指定對(duì)所有組件的屬性。

所有的組件都在指定的進(jìn)程中的主線程中實(shí)例化,系統(tǒng)調(diào)用這些組件就是從主線程里發(fā)出的,其他的線程將不會(huì)對(duì)每個(gè)組件再實(shí)例化,所有作為調(diào)用的回應(yīng)的這些方法,比如說View.onKeyDown()還是組件的生命周期函數(shù)等等都是運(yùn)行在這個(gè)主線程中的,這就意味著當(dāng)系統(tǒng)調(diào)用這個(gè)組件時(shí),這個(gè)組件不能長(zhǎng)時(shí)間的阻塞線程(比如說網(wǎng)絡(luò)操作,循環(huán)計(jì)算),因?yàn)檫@樣會(huì)阻塞這個(gè)進(jìn)程中的其他組件,你可以將很耗時(shí)的任務(wù)分到其他的線程中。

當(dāng)內(nèi)存不足或者有其他更緊急的進(jìn)程要求時(shí),Android系統(tǒng)可能關(guān)閉一個(gè)進(jìn)程,運(yùn)行在這個(gè)進(jìn)程中的應(yīng)用組件因此被銷毀,當(dāng)用戶又重新回來時(shí),進(jìn)程才被重新啟動(dòng)。

至于究竟要停止哪個(gè)進(jìn)程,android系統(tǒng)是通過衡量哪個(gè)進(jìn)程對(duì)用戶來說更重要來實(shí)現(xiàn)的

2、 線程

你可以限制你的應(yīng)用運(yùn)行在一個(gè)進(jìn)程中,但是有的時(shí)候你需要新開一個(gè)線程在后臺(tái)運(yùn)行,用戶界面需要隨時(shí)對(duì)用戶的要求做出反應(yīng),所以一些很耗時(shí)的工作應(yīng)該重新啟動(dòng)一個(gè)線程來做,以免阻塞主進(jìn)程。

Android系統(tǒng)提供了一系列方便的類來管理線程(Looper,Handler,HandlerThread)

3、 遠(yuǎn)程調(diào)用(Remote procedure calls)

Android系統(tǒng)有一個(gè)輕量級(jí)的遠(yuǎn)程調(diào)用機(jī)制(RPC)-----一個(gè)方法在本地調(diào)用,但是在遠(yuǎn)程執(zhí)行(在另外一個(gè)進(jìn)程里),返回給調(diào)用端的所有結(jié)果都必須的系統(tǒng)能理解的,將數(shù)據(jù)從本地進(jìn)程和地址空間傳遞到遠(yuǎn)程的進(jìn)程和地址空間,并在遠(yuǎn)端重新裝配,返回值的時(shí)候傳輸方向相反,android系統(tǒng)會(huì)去做這些傳輸?shù)墓ぷ鳎屇隳軌蚣芯矶x你的RPC

一個(gè)RPC接口只能包含方法,默認(rèn)的,即使是沒有值返回,所有的方法都是同步執(zhí)行的,就是說本地方法一直會(huì)阻塞直到遠(yuǎn)端的方法執(zhí)行完畢)。

簡(jiǎn)單的說,這個(gè)遠(yuǎn)程調(diào)用的機(jī)制是這樣工作的:

首先你需要用IDL(interface definition language)聲明你的RPC接口,然后android系統(tǒng)會(huì)使用aidl工具來形成一個(gè)java接口,并且這個(gè)java接口是本地進(jìn)程和遠(yuǎn)端進(jìn)程都可以獲得的,這個(gè)java接口包含了兩個(gè)內(nèi)部類,請(qǐng)看下圖:

這兩個(gè)內(nèi)部類有管理遠(yuǎn)程調(diào)用(你用IDL聲明的接口)的所以代碼,兩個(gè)內(nèi)部類都實(shí)現(xiàn)IBinder接口,一個(gè)是在本地(內(nèi)部)使用,這個(gè)你可以不用自己寫代碼,另外一個(gè)叫做Stub,繼承自Binder類的,包含所有完成進(jìn)程間通信(IPC)的代碼,他包含你在RPC接口中聲明的所有方法,你應(yīng)該繼續(xù)繼承Stub類來實(shí)現(xiàn)這些方法。

一般的,遠(yuǎn)端進(jìn)程應(yīng)該由一個(gè)service來管理(因?yàn)橐粋€(gè)service能通知系統(tǒng)關(guān)于這個(gè)進(jìn)程和他連接到的其他進(jìn)程)。

9、進(jìn)程的生命周期(Processes and lifecycles)

Android系統(tǒng)總是盡最大的努力來維持一個(gè)應(yīng)用的進(jìn)程,但系統(tǒng)的內(nèi)存不足時(shí)就可能需要關(guān)閉一些舊的進(jìn)程了,但是決定關(guān)閉哪個(gè)進(jìn)程呢,android系統(tǒng)把所以的進(jìn)程放進(jìn)一個(gè)重要性樹里,最低重要性的進(jìn)程將會(huì)被停止,系統(tǒng)有5種重要性等級(jí),重要性從高到低如下:

(1)、前臺(tái)進(jìn)程。一個(gè)前臺(tái)進(jìn)程是當(dāng)前執(zhí)行用戶請(qǐng)求的進(jìn)程,如果有如下的一種情形的那么他就是前臺(tái)進(jìn)程:

a、這個(gè)進(jìn)程里運(yùn)行著一個(gè)正在和用戶交互的Activity(這個(gè)Activity的onResume()方法被調(diào)用)。

b、這個(gè)進(jìn)程里有綁定到當(dāng)前正在和用戶交互的Activity的一個(gè)service

c、這個(gè)進(jìn)程里有一個(gè)service對(duì)象,這個(gè)service對(duì)象執(zhí)行了至少一個(gè)他生命周期的函數(shù)(onCreate(), onStart(), or onDestroy()).

d、這個(gè)進(jìn)程里有一個(gè)執(zhí)行了onReceive()方法的broadcastreceiver對(duì)象

只有一定數(shù)量的前臺(tái)進(jìn)程在任何時(shí)間都存在,他們只有在最后的時(shí)刻被停止---系統(tǒng)的內(nèi)存太少了而不能運(yùn)行這些僅有的前臺(tái)進(jìn)程了),一般的,在那個(gè)時(shí)刻,手機(jī)會(huì)重新設(shè)置內(nèi)存頁(yè)的狀態(tài),所以停止一些前臺(tái)的進(jìn)程是為了保持對(duì)用戶操作的快速響應(yīng)。

(2)可見進(jìn)程。一個(gè)可見進(jìn)程一個(gè)沒有任何前臺(tái)顯示的組件,但是仍然可以影響到用戶當(dāng)前屏幕所看見的東西,如果有如下的一種情形那么他就是可見進(jìn)程。

a、 這個(gè)進(jìn)程里一個(gè)Activity,但是這個(gè)Activity當(dāng)前不是在前臺(tái)顯示,但是仍然對(duì)用戶是可見的(這個(gè)Activity的onPause()方法被調(diào)用),比如說一個(gè)Activity調(diào)用一個(gè)dialog,那么這個(gè)dialog是當(dāng)前顯示的組件,這個(gè)Activity不是在前臺(tái)顯示,但是對(duì)用戶是可見的。

b、 這個(gè)進(jìn)程里有一個(gè)綁定到一個(gè)可見Activity(如上所述的Activity)的service

一個(gè)可見進(jìn)程是極端重要的,只有在為了顯示所有前臺(tái)進(jìn)程時(shí),即顯示前臺(tái)進(jìn)程都不夠時(shí),才會(huì)停止可見進(jìn)程。

(3)、服務(wù)進(jìn)程。一個(gè)服務(wù)進(jìn)程是一個(gè)通過startService()啟動(dòng)的但是沒有在前兩個(gè)分類中的進(jìn)程,雖然服務(wù)進(jìn)程不是用戶直接能看見的,但是他也總是做一些用戶很關(guān)心的事(如在后臺(tái)播放mp3,從網(wǎng)絡(luò)上下載東西),所以系統(tǒng)會(huì)一直保持服務(wù)進(jìn)程運(yùn)行,除非內(nèi)存不足以運(yùn)行服務(wù)進(jìn)程,前臺(tái)進(jìn)程,可見進(jìn)程。

(4)后臺(tái)進(jìn)程。一個(gè)后臺(tái)進(jìn)程是運(yùn)行一個(gè)當(dāng)前對(duì)用戶是不可見的Activity(這個(gè)Activity的onStop()被調(diào)用),這些進(jìn)程對(duì)用戶體驗(yàn)沒有什么直接的影響,當(dāng)內(nèi)存不足以運(yùn)行前臺(tái)進(jìn)程,可見進(jìn)程,服務(wù)進(jìn)程時(shí),可以隨時(shí)停止后臺(tái)進(jìn)程,通常有很多的后臺(tái)進(jìn)程在運(yùn)行,系統(tǒng)會(huì)把這些后臺(tái)進(jìn)程放進(jìn)一個(gè)LRU中(最近使用隊(duì)列),最近使用的就最后停止。

(5)空進(jìn)程。一個(gè)空進(jìn)程就是進(jìn)程里沒有任何活動(dòng)的應(yīng)用組件,維持這種進(jìn)程的唯一原因就是作為一種緩存,當(dāng)一個(gè)組件需要啟動(dòng)時(shí)加快啟動(dòng)的速度,系統(tǒng)為了平衡進(jìn)程緩存和核心緩存會(huì)停止這些空的進(jìn)程。

Android系統(tǒng)會(huì)取一個(gè)進(jìn)程里的所以組件的最高重要性來安排進(jìn)程的重要性,比如說,一個(gè)進(jìn)程里有一個(gè)service和一個(gè)可見的Activity,那么這個(gè)進(jìn)程會(huì)被安排成一個(gè)可見進(jìn)程,而不是服務(wù)進(jìn)程。

另外,一個(gè)進(jìn)程的重要性有可能會(huì)因?yàn)槠渌M(jìn)程的依賴而升高,一個(gè)進(jìn)程不能比他所服務(wù)的進(jìn)程的重要性低,比如有進(jìn)程A里的service綁定到了進(jìn)程B的組件上,那么進(jìn)程A的重要性至少和進(jìn)程B的一樣,或者更高。

因?yàn)橐粋€(gè)服務(wù)進(jìn)程的重要性比運(yùn)行一個(gè)后臺(tái)Activity的進(jìn)程高,所以,當(dāng)一個(gè)Activity做一些長(zhǎng)時(shí)間運(yùn)行的任務(wù)時(shí),最好啟動(dòng)一個(gè)service來做,而不是放到一個(gè)線程里去做,特別是這個(gè)任務(wù)的時(shí)間可能比Activity運(yùn)行的時(shí)間還長(zhǎng)的時(shí)候,比如在后臺(tái)播放音樂,或者上傳一張圖片到網(wǎng)上,使用一個(gè)service保證了這個(gè)任務(wù)至少是服務(wù)進(jìn)程的重要性,broadcast receiver也是一樣,長(zhǎng)時(shí)間運(yùn)行的任務(wù)也最好是放到一個(gè)service里,而不是放到一個(gè)線程里。


文章題目:一步一步揭開Android應(yīng)用程序的神秘面紗
URL鏈接:http://www.5511xx.com/article/coijdoc.html