## 我所見(jiàn)到的Activity ##
> 這里是我在開(kāi)發(fā)過(guò)程中所遇見(jiàn)的有關(guān)于Activity的一些知識(shí)分享
####1. Activity的生命周期圖示![Alt text](./0_1314838777He6C.gif.png)####1.1 Activity生命周期中的四種狀態(tài)1.在屏幕的前臺(tái)(Activity活動(dòng)棧棧頂),叫做活動(dòng)狀態(tài)或者運(yùn)行狀態(tài)(active or running)2.如果一個(gè)Activity失去焦點(diǎn)你雌,但是依然可見(jiàn)(一個(gè)新的非全屏的Activity 或者一個(gè)透明的Activity 被放置在棧頂),叫做暫停狀態(tài)(Paused)拨拓。一個(gè)暫停狀態(tài)的Activity依然保持活力(保持所有的狀態(tài)渣磷,成員信息,和窗口管理器保持連接)竟宋,但是在系統(tǒng)內(nèi)存極端低下的時(shí)候?qū)⒈粴⒌簟?.如果一個(gè)Activity被另外的Activity完全覆蓋掉形纺,叫做停止?fàn)顟B(tài)(Stopped)。它依然保持所有狀態(tài)和成員信息蜗字,但是它不再可見(jiàn)脂新,所以它的窗口被隱藏,當(dāng)系統(tǒng)內(nèi)存需要被用在其他地方的時(shí)候级零,Stopped的Activity將被殺掉滞乙。4.如果一個(gè)Activity是Paused或者Stopped狀態(tài),系統(tǒng)可以將該Activity從內(nèi)存中刪除亥贸,Android系統(tǒng)采用兩種方式進(jìn)行刪除浇垦,要么要求該Activity結(jié)束男韧,要么直接殺掉它的進(jìn)程。當(dāng)該Activity再次顯示給用戶(hù)時(shí)此虑,它必須重新開(kāi)始和重置前面的狀態(tài)朦前。#####1.2Activity切換時(shí)的方法調(diào)用順序Activity1 ----- startActivity()------> Activity2 ----- startActivity() ------->Activity1```onCreate::mainonStart::mainonResume::mainonPause::mainonCreate::otheronStart::otheronResume::otheronStop::mainonPause::otheronCreate::mainonStart::mainonResume::mainonStop::other```Activity1 ----- startActivity()------> Activity2 ----- back ------->Activity1```onCreate::mainonStart::mainonResume::mainonPause::mainonCreate::otheronStart::otheronResume::otheronStop::mainonPause::otheronRestart::mainonStart::mainonResume::mainonStop::otheronDestroy::other```####2. Activity的啟動(dòng)模式>在Android中每個(gè)界面都是一個(gè)Activity鹃操,切換界面操作其實(shí)是多個(gè)不同Activity之間的實(shí)例化操作荆隘。在Android中Activity的啟動(dòng)模式?jīng)Q定了Activity的啟動(dòng)運(yùn)行方式赴背。Activity啟動(dòng)模式設(shè)置:``````#####2.1 Activity的四種啟動(dòng)模式及使用場(chǎng)景1.standard默認(rèn)啟動(dòng)模式,每次激活A(yù)ctivity時(shí)都會(huì)創(chuàng)建Activity實(shí)例燃观,并放入任務(wù)棧中便瑟。2.singleTop如果在任務(wù)的棧頂正好存在該Activity的實(shí)例, 就重用該實(shí)例积锅,否者就會(huì)創(chuàng)建新的實(shí)例并放入棧頂(即使棧中已經(jīng)存在該Activity實(shí)例养盗,只要不在棧頂往核,都會(huì)創(chuàng)建實(shí)例)嚷节。>singleTop適合接收通知啟動(dòng)的內(nèi)容顯示頁(yè)面。例如衩婚,某個(gè)新聞客戶(hù)端的新聞內(nèi)容頁(yè)面效斑,如果收到10個(gè)新聞推送,每次都打開(kāi)一個(gè)新聞內(nèi)容頁(yè)面是很煩人的奇昙。3.singleTask如果已經(jīng)存在一個(gè)task與新activity親和度(taskAffinity)一樣敌完,則activity將啟動(dòng)到該task。如果不是什湘,就啟動(dòng)一個(gè)新task。同一個(gè)application里面涧卵,每個(gè)activity的taskAffinity默認(rèn)都是一樣的腹尖。如果在棧中已經(jīng)有該Activity的實(shí)例热幔,就重用該實(shí)例(會(huì)調(diào)用實(shí)例的onNewIntent())。重用時(shí)近尚,會(huì)移除它上面的所有實(shí)例, 讓該實(shí)例回到棧頂场勤。如果棧中不存在該實(shí)例,將會(huì)創(chuàng)建新的實(shí)例放入棧頂格遭。>singleTask適合作為程序入口點(diǎn)留瞳。例如瀏覽器的主界面她倘。不管從多少個(gè)應(yīng)用啟動(dòng)瀏覽器,只會(huì)啟動(dòng)主界面一次前硫,其余情況都會(huì)走onNewIntent荧止,并且會(huì)清空主界面上面的其他頁(yè)面。4.singleInstance在一個(gè)新棧中創(chuàng)建該Activity實(shí)例嗤详,并讓多個(gè)應(yīng)用共享改棧中的該Activity實(shí)例瓷炮。一旦改模式的Activity的實(shí)例存在于某個(gè)棧中娘香,任何應(yīng)用再激活改Activity時(shí)都會(huì)重用該棧中的實(shí)例办龄,其效果相當(dāng)于多個(gè)應(yīng)用程序共享一個(gè)應(yīng)用淋昭,不管誰(shuí)激活該Activity都會(huì)進(jìn)入同一個(gè)應(yīng)用中。>singleInstance適合需要與程序分離開(kāi)的頁(yè)面英融。例如鬧鈴提醒歇式,將鬧鈴提醒與鬧鈴設(shè)置分離材失。singleInstance不要用于中間頁(yè)面,如果用于中間頁(yè)面笼呆,跳轉(zhuǎn)會(huì)有問(wèn)題旨别,比如:A -> B (singleInstance) -> C,完全退出后境肾,再次啟動(dòng)胆屿,首先打開(kāi)的是B非迹。#####2.2 關(guān)于onNewIntent()方法>前提:ActivityA已經(jīng)啟動(dòng)過(guò),處于當(dāng)前應(yīng)用的Activity活動(dòng)棧中;*當(dāng)ActivityA的LaunchMode為SingleInstance,SingleTask時(shí),如果已經(jīng)ActivityA已經(jīng)在活動(dòng)棧中纯趋,那么此時(shí)會(huì)調(diào)用onNewIntent()方法*當(dāng)ActivityA的LaunchMode為Standard時(shí)吵冒,由于每次啟動(dòng)ActivityA都是啟動(dòng)新的實(shí)例,和原來(lái)啟動(dòng)的沒(méi)關(guān)系亿汞,所以不會(huì)調(diào)用原來(lái)ActivityA的onNewIntent方法當(dāng)調(diào)用到onNewIntent(intent)的時(shí)候揪阿,需要在onNewIntent() 中使用setIntent(intent)賦值給Activity的Intent.否則,后續(xù)的getIntent()都是得到老的Intent吴裤。而且系統(tǒng)可能會(huì)隨時(shí)殺掉后臺(tái)運(yùn)行的Activity,如果這一切發(fā)生钮蛛,那么系統(tǒng)就會(huì)調(diào)用onCreate方法剖膳,而不調(diào)用onNewIntent方法潮秘,一個(gè)好的解決方法就是在onCreate和onNewIntent方法中調(diào)用同一個(gè)處理數(shù)據(jù)的方法.```public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);processExtraData();}protected void onNewIntent(Intent intent) {super.onNewIntent(intent);setIntent(intent);//must store the new intent unless getIntent() will return the old oneprocessExtraData()}private void processExtraData(){Intent intent = getIntent();//use the data received here}```####3. 關(guān)于onActivityResult不執(zhí)行問(wèn)題在startActivityForResult()使用時(shí),若要onActivityResult()方法能正常工作那么必須將被啟動(dòng)Activity的啟動(dòng)模式設(shè)置為`standard`或者`singleTop`.####4. 使用intent傳遞對(duì)象Android中Intent傳遞類(lèi)對(duì)象提供了兩種方式-實(shí)現(xiàn)Serializable接口傳遞對(duì)象-實(shí)現(xiàn)Parcelable接口傳遞對(duì)象柜候。Intent中傳遞這2種對(duì)象的方法:```Bundle.putSerializable(Key,Object);? //實(shí)現(xiàn)Serializable接口的對(duì)象Bundle.putParcelable(Key, Object); //實(shí)現(xiàn)Parcelable接口的對(duì)象```####5. screenOrientation屬性#####5.1 screenOrientation屬性介紹-"unspecified":默認(rèn)值 由系統(tǒng)來(lái)判斷顯示方向.判定的策略是和設(shè)備相關(guān)的渣刷,所以不同的設(shè)備會(huì)有不同的顯示方向.-"landscape":橫屏顯示(寬比高要長(zhǎng))-"portrait":豎屏顯示(高比寬要長(zhǎng))-"user":用戶(hù)當(dāng)前首選的方向-"behind":和該Activity下面的那個(gè)Activity的方向一致(在Activity活動(dòng)棧中的)-"sensor":有物理的感應(yīng)器來(lái)決定矗烛。如果用戶(hù)旋轉(zhuǎn)設(shè)備這屏幕會(huì)橫豎屏切換瞭吃。-"nosensor":忽略物理感應(yīng)器,這樣就不會(huì)隨著用戶(hù)旋轉(zhuǎn)設(shè)備而更改了("unspecified"設(shè)置除外)股冗。#####5.2 屬性設(shè)置1.配置文件中```android:screenOrientation="portrait",? 為豎屏顯示。android:screenOrientation="landscape"和蚪,為橫屏顯示止状。```2.代碼中```setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)```#####5.3 橫豎屏對(duì)應(yīng)不同的布局文件如果要讓軟件在橫豎屏之間切換,由于橫豎屏的高寬會(huì)發(fā)生轉(zhuǎn)換攒霹,有可能會(huì)要求不同的布局怯疤。可以通過(guò)以下方法來(lái)切換布局:1.在res目錄下建立layout-land和layout-port目錄,相應(yīng)的layout文件不變催束,比如main.xml集峦。layout-land是橫屏的layout,layout-port是豎屏的layout,其他的不用管,模擬器會(huì)自動(dòng)尋找少梁。2.通過(guò) this.getResources().getConfiguration().orientation來(lái)判斷當(dāng)前是橫屏還是豎屏然后來(lái)加載相應(yīng)的 xml布局文件。因?yàn)楫?dāng)屏幕變?yōu)闄M屏的時(shí)候,系統(tǒng)會(huì)重新呼叫當(dāng)前Activity的onCreate方法,你可以把以下方法放在你的onCreate中來(lái)檢查當(dāng)前的方向,然后可以讓你的setContentView來(lái)載入不同的layout xml.####6. configChanges屬性>當(dāng)你的Activity正顯示在屏幕上時(shí), 如果這時(shí)候手機(jī)的一些配置(比如: 橫豎屏切換, 鍵盤(pán)的可用性等)發(fā)生了改變, 那么系統(tǒng)就會(huì)調(diào)用`onConfigurationChanged`方法. 注意, 只有當(dāng)你在配置文件中選定`configChanges`屬性時(shí)才會(huì)被調(diào)用, 不然就會(huì)通過(guò)正常的生命周期重啟Activity.#####6.1 configChanges屬性對(duì)Activity生命周期的影響1.未設(shè)置configChanges切換成橫屏?xí)r的方法調(diào)用```onPause-->onSaveInstanceState-->onStop-->onCreate-->onStart-->onRestoreInstanceState-->onResume-->```切換成豎屏?xí)r的方法調(diào)用```onResume-->onSaveInstanceState-->onPause-->onStop-->onCreate-->onStart-->onRestoreInstanceState-->onResume-->```2.Activity添加 android:configChanges="orientation|screenSize">為啥orientation, screenSize倆值為啥必須合用這個(gè)目前還搞不懂切換成橫屏?xí)r的方法調(diào)用```onConfigurationChanged-->```切換成豎屏?xí)r的方法調(diào)用```onConfigurationChanged-->```#####6.2 configChanges屬性介紹-"mcc" :國(guó)際移動(dòng)用戶(hù)識(shí)別碼所屬?lài)?guó)家代號(hào)改變了-----? sim被偵測(cè)到了凯沪,去更新mcc第焰,mcc是移動(dòng)用戶(hù)所屬?lài)?guó)家代號(hào)-"mnc": 國(guó)際移動(dòng)用戶(hù)識(shí)別碼的移動(dòng)網(wǎng)號(hào)碼改變了------ sim被偵測(cè)到了,去更新mnc妨马,MNC是移動(dòng)網(wǎng)號(hào)碼挺举,最多由兩位數(shù)字組成,用于識(shí)別移動(dòng)用戶(hù)所歸屬的移動(dòng)通信網(wǎng)-"locale": 地址改變了-----用戶(hù)選擇了一個(gè)新的語(yǔ)言會(huì)顯示出來(lái)-"touchscreen": 觸摸屏是改變了------通常是不會(huì)發(fā)生的-"keyboard" :鍵盤(pán)發(fā)生了改變----例如用戶(hù)用了外部的鍵盤(pán)-"keyboardHidden": 鍵盤(pán)的可用性發(fā)生了改變-"navigation": 導(dǎo)航發(fā)生了變化-----通常也不會(huì)發(fā)生-"screenLayout": 屏幕的顯示發(fā)生了變化------不同的顯示被激活-"fontScale": 字體比例發(fā)生了變化----選擇了不同的全局字體-"uiMode": 用戶(hù)的模式發(fā)生了變化-"orientation": 屏幕方向改變了-"screenSize": 屏幕大小改變了-"smallestScreenSize": 屏幕的物理大小改變了烘跺,如:連接到一個(gè)外部的屏幕上####擴(kuò)展#####1. Android下Context湘纵、Activity、Application之間有什么區(qū)別首先Activity和Application都是Context的子類(lèi)滤淳。Context從字面上理解就是上下文的意思梧喷,在實(shí)際應(yīng)用中它也確實(shí)是起到了管理上下文環(huán)境中各個(gè)參數(shù)和變量的總用,方便我們可以簡(jiǎn)單的訪(fǎng)問(wèn)到各種資源脖咐。雖然Activity和Application都是Context的子類(lèi)铺敌,但是他們維護(hù)的生命周期不一樣。前者維護(hù)一個(gè)Acitivity的生命周期屁擅,所以其對(duì)應(yīng)的Context也只能訪(fǎng)問(wèn)該activity內(nèi)的各種資源偿凭。后者則是維護(hù)一個(gè)Application的證明周期。>還有就是派歌,在使用context的時(shí)候弯囊,小心內(nèi)存泄露,防止內(nèi)存泄露胶果,注意一下幾個(gè)方面:1.不要讓生命周期長(zhǎng)的對(duì)象引用activity context匾嘱,即保證引用activity的對(duì)象要與activity本身生命周期是一樣的2.對(duì)于生命周期長(zhǎng)的對(duì)象,可以使用application context3.避免非靜態(tài)的內(nèi)部類(lèi)早抠,盡量使用靜態(tài)類(lèi)奄毡,避免生命周期問(wèn)題,注意內(nèi)部類(lèi)對(duì)外部對(duì)象引用導(dǎo)致的生命周期變化####參考鏈接[Android中Activity四種啟動(dòng)模式和taskAffinity屬性詳解](http://blog.csdn.net/zhangjg_blog/article/details/10923643)