????????這是《第一行代碼》閱讀手札的第二篇顺饮,也就是原書的《探究活動》章節(jié)努溃。上一篇今布,主要講述了Android的架構(gòu)经备,開發(fā)工具,日志的使用等最基本的介紹险耀,本章節(jié)主要介紹Activity的相關(guān)內(nèi)容
關(guān)鍵字:Activity弄喘,Intent玖喘,Activity的生命周期甩牺,Activity的四種啟動方式
?????????Activity作為四大組件中使用率最頻繁的組件,其作用和重要性不言而喻累奈,Activtity就是展示當(dāng)前頁面控件的容器贬派,當(dāng)然這是我個人的理解(更多人叫它活動)在AndroidStudio中(以下簡稱AS)在新建項目的時候,系統(tǒng)會要求我們創(chuàng)建一個Activity
????????AS為我們提供了多選擇的activity(雖然用的最多的就是Empty Activity)澎媒,創(chuàng)建完項目以后搞乏,我們先去src目錄下,找到清單文件(也就是AndroidManifest.xml)看到xml文件戒努,對于XML请敦,我的第一印象就是標(biāo)簽語言可作為資源配置文件镐躲,可以使用Xmlpull解析器等其他解析去獲取配置信息等等,
? ? ? ? ?那么侍筛,先看看Android清單文件里面萤皂,最基本的配置
application,也就是全局apk的配置匣椰,所有的四大組件均在里面注冊(可以看到application標(biāo)簽是一個很大的閉包)首先分析application
allowBackup : 老實說裆熙,筆者原來沒怎么注意到這個標(biāo)簽,今天查資料才發(fā)現(xiàn)我的天禽笑,這個標(biāo)簽不得了入录,標(biāo)簽定義:是否允許備份系統(tǒng)和用戶數(shù)據(jù)的屬性。(默認(rèn)是true佳镜,也就是允許備份)也就是說明僚稿,應(yīng)用程序數(shù)據(jù)可以在手機(jī)未獲取 ROOT的情況下通過adb調(diào)試工具來備份和恢復(fù),這就允許惡意攻擊者在接觸用戶手機(jī)的情況下在短時間內(nèi)啟動手機(jī) USB 調(diào)試功能蟀伸,來竊取那些能夠受到AllowBackup 漏洞影響的應(yīng)用的數(shù)據(jù)(鄭秋冬盜取數(shù)據(jù)贫奠?),造成用戶隱私泄露甚至財產(chǎn)損失望蜡。具體的細(xì)節(jié)就不在深究唤崭,這里推薦一篇博客,allowbackup相關(guān)
icon : 也就是應(yīng)用的圖標(biāo)脖律,比如手機(jī)上的企鵝谢肾,12306的鐵路標(biāo)識等等
label : 指定標(biāo)題欄的內(nèi)容,需要注意的是小泉,給主活動(程序入口的activity)設(shè)置指定的label不僅會成為標(biāo)題欄中的內(nèi)容芦疏,還會成為啟動器中應(yīng)用程序的名稱
supportsRtl :?聲明你的application是否愿意支持從右到左(原來RTL就是right-to-left 的縮寫...)的布局。如果設(shè)置為true微姊,targetSdkVersion設(shè)置為17或更高酸茴,各種RTL的API將被激活,系統(tǒng)使用您的應(yīng)用程序可以顯示RTL布局兢交。如果targetSdkVersion設(shè)置為16或更低的設(shè)置為false薪捍,RTL的API將被忽略或沒有影響您的應(yīng)用程序?qū)⒕哂邢嗤男袨闊o論對用戶現(xiàn)場的選擇相關(guān)的布局方向(你的布局會從左至右)。沒事配喳,可能你已經(jīng)蒙圈了酪穿,繼續(xù)奉獻(xiàn)博客一篇了解supportsRtl
theme : 也就是主題,關(guān)于theme比較好的理解就是晴裹,假設(shè)我現(xiàn)在需要將一個Activity變成對話框被济,也就是類似于這種的效果,(當(dāng)然你說我只用Dialog也可以實現(xiàn)需求涧团,這里只是為了更好的理解和演示所以請各位看官輕噴)
那么只磷,這個時候经磅,就可以設(shè)置Activity的樣式,也就是將其theme,改成我們自己定義的style钮追。關(guān)于Application的基本標(biāo)簽內(nèi)容就是這些馋贤,當(dāng)然,我們自定義application畏陕,需要設(shè)置name標(biāo)簽等
接下來配乓,就是activity這個標(biāo)簽的說明:
name:也就是這個Activity的名稱,你自己定義的Activity的名稱
intent filter :也稱意圖過濾器惠毁。試想這樣一種場景犹芹,如果一個 Intent 請求在一片數(shù)據(jù)上執(zhí)行一個動作, Android 如何知道哪個應(yīng)用程序(和組件)能用來響應(yīng)這個請求呢鞠绰?Intent Filter的出現(xiàn)就是為了解決這個問題(本質(zhì)是根據(jù)設(shè)置的條件去過濾)腰埂,它是用來注冊 Activity 、 Service 和 Broadcast Receiver蜈膨,讓其 具有能在某種數(shù)據(jù)上執(zhí)行一個動作的能力屿笼。使用 Intent Filter ,應(yīng)用程序組件就會告知 Android 翁巍,它們能為其它程序的組件的動作請求提供服務(wù)驴一,包括同一個程序的組件、本地的或第三方的應(yīng)用程序灶壶。
關(guān)于intent fiflter的拓展:
intent fiflter 的一條元素至少應(yīng)該包含一個 action肝断,否則任何Intent請求都不能和該intent fiflter匹配。如果Intent請求的Action中和某某一條匹配驰凛,那么該Intent就通過了這條intent fiflter的動作測試胸懈。如果Intent請求或intent fiflter中沒有說明具體的Action類型,那么會出現(xiàn)下面兩種情況恰响。
(1) 如果intent fiflter中沒有包含任何Action類型趣钱,那么無論什么Intent請求都無法和這條匹配;
(2) 反之胚宦,如果Intent請求中沒有設(shè)定Action類型首有,那么只要intent-filter中包含有Action類型间唉,這個Intent請求就將順利地通過的行為測試绞灼。
因此,當(dāng)意圖過濾器設(shè)置為?action android:name="android.intent.action.MAIN",即聲明印叁,該注冊的Activity昨悼,為當(dāng)前應(yīng)用的主入口點
Activity:
Activity作為四大組件中使用最頻繁的組件(簡單理解终议,就是界面)两曼,其作用不言而喻,首先渐夸,需要繼承系統(tǒng)的Activity或者AppCompatActivity,既然是系統(tǒng)的類,那么肯定要實現(xiàn)(重寫)一些系統(tǒng)的方法去私人訂制,比如棒拂,設(shè)置具體的View,點擊事件牢屋,跳轉(zhuǎn)新的界面等等,
首先,既然是新創(chuàng)建Activity涮拗。
第一步乾戏,需要去清單文件去配置注冊,AS默認(rèn)在新創(chuàng)建Activity之后會去清單文件配置注冊,但還是建議自己去檢查一下是否正常注冊从藤,假設(shè)未在清單文件里面注冊(也就是配置Activity的名字),如果從當(dāng)前的Activity跳轉(zhuǎn)到未注冊界面會報如下異常:
其次,既然是不同的Activity,肯定需要展示不同的內(nèi)容灌曙,那么逆害,一般我們通過 調(diào)用這個方法setContentView(布局文件)去展示不同的View纯陨。
Intent:
Intent,是Android程序中各組件之間進(jìn)行交互的一種重要方式,它不僅可以指明當(dāng)前組件想要執(zhí)行的動作尤勋,還可以在不同組件之前傳遞數(shù)據(jù)最冰。Intent一般可以用于啟動活動(也就是跳轉(zhuǎn)界面)达布,啟動服務(wù)以及發(fā)送廣播分冈,因此圾另,Intent在這里起著一個媒體中介的作用,專門提供組件互相調(diào)用的相關(guān)信息雕沉。
意圖的屬性包括:Action(動作)集乔,Category(附加信息),Data(數(shù)據(jù),具體內(nèi)容)扰路,Tpye(類型)等等尤溜,舉個例子,說白了意圖就是啟動一個組件的的完整的動作信息汗唱。
就像玩游戲宫莱,玩就是Action動作,游戲就是Data內(nèi)容哩罪,而Type就是類型授霸,玩什么呢?玩夢幻际插,type就是指的類型碘耳,只有這些信息全了才能執(zhí)行一個完整的意圖,當(dāng)然還有一些信息框弛,比如scheme就是URI類型的數(shù)據(jù)的前綴辛辨,sms,還有host主機(jī)名瑟枫,path路徑等斗搞。
Intent分為以下兩種:
顯式意圖:簡單理解,就是簡單明了顯示的意圖力奋,也就是毫不顧忌的從當(dāng)前Activity跳轉(zhuǎn)到另外一個Activity榜旦,一般直接調(diào)用:
startActivity (new Intent (this ,LoginActivity.class) );
這是Intent的一個重載方法景殷,參數(shù)說明:
參數(shù)一:當(dāng)前上下文對象
參數(shù)二:也就是你要跳轉(zhuǎn)到具體的Activity
既然有顯式意圖溅呢,那么與之對應(yīng),應(yīng)該有隱式意圖猿挚。
隱式意圖咐旧,即Intent的發(fā)送者在構(gòu)造Intent對象時,并不知道也不關(guān)心接收者是誰绩蜻,這樣有利于降低發(fā)送者和接收者之間的耦合铣墨,它一般用在沒有明確指出目標(biāo)組件名稱的前提下,一般是用于在不同應(yīng)用程序之間办绝,如下:
Intent?it?=?new?Intent();
it.setAction("com.google.test");
startActivity(it);
由于隱式意圖伊约,?沒有指明接收者,?只是給了一個action作為接收者的過濾條件孕蝉。
對于顯式Intent屡律,Android不需要去做解析,因為目標(biāo)組件已經(jīng)很明確降淮,Android需要解析的是那些隱式Intent超埋,通過解析,將Intent映射給可以處理此Intent的Activity、IntentReceiver或Service霍殴。
當(dāng)然媒惕,在隱式意圖這種情況下,開啟新的Activity需要在清單文件配置相對應(yīng)的參數(shù)
界面跳轉(zhuǎn)傳遞數(shù)據(jù)
跳轉(zhuǎn)界面来庭,并從當(dāng)前Activity跳轉(zhuǎn)到新的Activity妒蔚,是很常見的。那么根據(jù)這種跳轉(zhuǎn)界面并傳遞數(shù)據(jù)的情況巾腕,就分為以下兩種情形面睛,
A:從當(dāng)前界面(姑且稱為First)跳轉(zhuǎn)到新界面(姑且稱為Second)絮蒿,從First將數(shù)據(jù)傳遞給Second尊搬,Second來接受數(shù)據(jù)并使用,(這種場景是非常常見的)
B:從當(dāng)前界面(依舊稱為First)跳轉(zhuǎn)到新界面(依舊稱為Second),從First將數(shù)據(jù)傳遞給Second土涝,Second來接受數(shù)據(jù)并使用佛寿,但是當(dāng)Second界面關(guān)閉或者按下返回鍵的時候,需要將結(jié)果回傳給First
先來討論A情形但壮,
首先冀泻,在First中傳遞數(shù)據(jù)的寫法:
Intent intent = new Intent (FirstActivity.this,SecondActivity.class); //這里使用Bundle攜帶數(shù)據(jù)并傳遞
Bundle?bundle?= new Bundle();?
bundle.putString("skip", "從FirstActivity傳遞數(shù)據(jù)到SecondActivity"); ?
參數(shù)一:需要跟新界面的Key完全一致
參數(shù)二:傳遞的數(shù)據(jù)
intent.putExtras(bundle);
startActivity(intent);
那么蜡饵,在Second中弹渔,因為數(shù)據(jù)已經(jīng)從First傳遞過來了,那么接受First的數(shù)據(jù)寫法如下:
Bundle bundle = getIntent().getExtras();?
String dataInfo= bundle.getString("skip"); ?//括號里面的Key需要和First傳遞過來的key符合一致
其中溯祸,這里的dataInfo,就是從first中獲取到的數(shù)據(jù)
接下來肢专,討論B情形
首先,在First中焦辅,開啟Second的方式需要變成如下API
startActivityForResult(Intent intent, int requestCode);
參數(shù)一:intent實例化對象
參數(shù)二:如果 requestCode?> = 0,當(dāng)Activity結(jié)束時 requestCode 將歸還在onActivityResult()中博杖。以便確定返回的數(shù)據(jù)是從哪個Activity中返回(簡單理解,就是一個標(biāo)識)
接著筷登,在First中剃根,調(diào)用onActivityResult(int requestCode, int resultCode, Intent data)
參數(shù)一:這個整數(shù)requestCode提供給onActivityResult,是以便確認(rèn)返回的數(shù)據(jù)是從哪個Activity返回的前方。
這個requestCode和上面startActivityForResult()中的requestCode相對應(yīng)狈醉,也就是需要匹配標(biāo)識。
參數(shù)二:這整數(shù)resultCode是由Second通過其setResult()方法返回惠险。
參數(shù)三:Intent實例化對象苗傅,這個data,就是返回的數(shù)據(jù)。
最后莺匠,在second中金吗,(因為你的數(shù)據(jù)需要傳到A,所以,必須通過Intent將數(shù)據(jù)傳遞出去)
調(diào)用:setResult(int resultCode, Intent data) 摇庙,此方法把Second想要返回的數(shù)據(jù)返回到first
參數(shù)一:當(dāng)Activity結(jié)束時旱物,resultCode將歸還在onActivityResult()中,一般為RESULT_CANCELED , RESULT_OK卫袒。
參數(shù)二:一個Intent對象宵呛,返回給first的數(shù)據(jù)。(與步驟二相對應(yīng))
這樣既可滿足情形二的需求夕凝。
返回棧
Android是使用任務(wù)Tsk來管理活動(Activity)的宝穗,一個任務(wù)就是一組存放在棧里面的活動集合,這個棧也被稱為返回棧码秉。棧是一種后進(jìn)先出的數(shù)據(jù)結(jié)構(gòu)逮矛,默認(rèn)情況下,每當(dāng)我們啟動了一個新的活動转砖,它會在返回棧中入棧须鼎,并處于棧頂?shù)奈恢谩:唵卫斫饩褪歉幔?dāng)我們按下返回鍵或者手動finish方法去銷毀活動時晋控,處于棧頂?shù)幕顒訒鰲#@時姓赤,前一個入棧的活動赡译,就會重新處于棧頂?shù)奈恢谩O到y(tǒng)總是會顯示處于棧頂?shù)幕顒咏o用戶不铆。
活動狀態(tài)
1:運行狀態(tài)
當(dāng)一個活動處于棧頂?shù)臅r候蝌焚,這時活動就處于棧頂運行狀態(tài)。系統(tǒng)最不愿意回收的就是處于被運行狀態(tài)的活動狂男,(運行的你強(qiáng)制銷毀综看,那就呵呵噠)
2:暫停狀態(tài)
當(dāng)一個活動不再處于棧頂位置,但依舊可見這時活動就進(jìn)入了暫停狀態(tài)岖食,簡單的理解就是红碑,對話框形式的Activity只會占用屏幕中間的部分區(qū)域,你很快就會看到后面的Activity泡垃,處于暫停狀態(tài)的活動仍然是完全存活著的析珊,系統(tǒng)也不愿意去回收這種活動(因為他還是可見的,只是暫時無法使用蔑穴,但它時刻準(zhǔn)備著供用戶使用)忠寻;只有當(dāng)內(nèi)存極低的情況下,系統(tǒng)才會去考慮回收這種活動存和。
3:停止?fàn)顟B(tài)
當(dāng)一個Activity不再處于棧頂位置奕剃,并且完全不可見的時候衷旅,就進(jìn)入了停止?fàn)顟B(tài)。系統(tǒng)依舊會為這種活動保存相應(yīng)的狀態(tài)和成員變量纵朋,但是這并不是完全可靠的柿顶,當(dāng)其他地方需要內(nèi)存的時候,處于停止?fàn)顟B(tài)的活動有可能會被系統(tǒng)回收操软。
4:銷毀狀態(tài)
當(dāng)一個Activity從返回棧中移除后就變成了銷毀狀態(tài)嘁锯。系統(tǒng)優(yōu)先會回收處于這種狀態(tài)的活動,從而保證手機(jī)的內(nèi)存聂薪,提高運行效率家乘。
活動的生命周期:
關(guān)于Activity的生命周期,額藏澳,還是上圖吧仁锯,雖然老司機(jī)們已經(jīng)不想在看生命周期的東西了
關(guān)于生命周期,這里就不多說什么笆载,
總之認(rèn)準(zhǔn)一個理扑馁,在onCreate里面做加載,初始化的事情凉驻;在onDestory里面做釋放資源,解綁的事情复罐。這樣理解涝登,準(zhǔn)沒錯。
Activity的啟動模式:
啟動模式是指,可以根據(jù)實際開發(fā)需求為Activity設(shè)置對應(yīng)的啟動模式效诅,從而可以避免創(chuàng)建大量重復(fù)的Activity等問題胀滚。
1)standard
standard為Activity的默認(rèn)啟動模式,可以不用寫配置乱投。在這個模式下咽笼,都會默認(rèn)創(chuàng)建一個新的實例(處于棧頂)。因此戚炫,在這種模式下剑刑,可以有多個相同的實例,也允許多個相同Activity疊加双肤。(點back鍵會依照棧順序依次退出)
2)singleTop
singleTop模式下,Activity可以有多個實例施掏,但是不允許多個相同Activity疊加。即茅糜,如果Activity在棧頂?shù)臅r候七芭,啟動相同的Activity,不會創(chuàng)建新的實例蔑赘,而會調(diào)用其onNewIntent方法狸驳。
3)singleTask
singleTask表示只有一個實例预明。在同一個應(yīng)用程序中啟動他的時候,若Activity不存在耙箍,則會在當(dāng)前task創(chuàng)建一個新的實例贮庞,若存在,則會把task中在其之上的其它Activity destory掉并調(diào)用它的onNewIntent方法。如果是在別的應(yīng)用程序中啟動它垢粮,則會新建一個task渤早,并在該task中啟動這個Activity,singleTask允許別的Activity與其在一個task中共存遮斥,也就是說,如果我在這個singleTask的實例中再打開新的Activity扇丛,這個新的Activity還是會在singleTask的實例的task中术吗。
4)singleInstance
只有一個實例,并且這個實例獨立運行在一個task中(會有一個單獨的返回棧來管理這個活動)帆精,這個task只有這個實例较屿,不允許有別的Activity存在。
總結(jié):書中第二章的基本內(nèi)容就是這些卓练,
學(xué)而不思則罔隘蝎,思而不學(xué)則殆。加油襟企!
如果這篇文章對您有開發(fā)or學(xué)習(xí)上的些許幫助嘱么,希望各位看官留下寶貴的star,謝謝顽悼。
Ps:著作權(quán)歸作者所有,轉(zhuǎn)載請注明作者, 商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán)曼振,非商業(yè)轉(zhuǎn)載請注明出處(開頭或結(jié)尾請?zhí)砑愚D(zhuǎn)載出處,添加原文url地址),文章請勿濫用,也希望大家尊重筆者的勞動成果