Hi,你們好,又見面啦,上一期咱們講了如何安裝AS,是否是已經有小夥伴火燒眉毛的建立了本身的項目並開始嘗試了呢?那麼這一期咱們主要爲你們介紹Activity。做爲Android的四大組件之一,Activity佔據着很是重要的做用。本文將圍繞Android的生命週期、啓動模式、基本配置等方面進行介紹。java
應用程序的每個界面都是一個Activity,因此也有人稱其爲視圖界面。從字面的意思去理解,Activity具備活動的意思,咱們在應用中進行的操做都是集中在Activity上面完成,例如撥號、拍照、發送email、看地圖。每個activity被給設置到一個窗口,在上面能夠繪製交互界面。 一個應用程序一般由多個activities組成,他們一般是鬆耦合關係,一般一個應用程序包含有一個主Activity,即點擊桌面圖標的時候首先進入的Activity。android
以一個簡單的Activity的建立與使用示說明:面試
在Androd Studio 新建項目完成後,會自動建立一個 Java 文件,這個文件就是 Activity,由於它繼承系統 framework 層提供的 Activity,這裏 AppCompatActivity 是 Activity 的子類,咱們的 MainActivity 間接繼承 Activity。數據結構
而且你會看到 MainActivity 強制重寫了 onCreate 方法,在 onCreate 中,經過 setContentView 爲 Activity 設置咱們自定義的頁面佈局文件。app
在 manifest 中註冊Activityide
<activity android:name=".MainActivity" android:configChanges="orientation|screenSize" android:label="@string/app_name" android:launchMode="standard"> <intent-filter> <action android:name="myactoin2" /> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
Activity 必須在 AndroidManifest.xml 註冊,若是沒有註冊這 Activity 就不能正常運行,其實在正常狀況下在使用Android 中的四大組件(Activity,Service,BrocastReceiver,ContentProvider)時都須要再 AndroidManifest.xml 中註冊。在上面的 xml 註冊信息中,其中 <inten-filter>中指定佈局
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
代表這個Activity是主Activity,在Android系統點擊應用圖標首先進入主Activity。動畫
Activity是經過Intent用來在應用程序的Activity間啓動、中止和傳輸。this
啓動Activity的三種方法:spa
一、顯示啓動
在這裏註冊了第二個Activity ---- SecondActivity ,而且牢記前面的註冊操做,咱們把 SecondActivity 註冊到 Manifest 文件中。如今就能夠在 MainActivity 中啓動 SecondActivity。
Intent intent = new Intent(this, SecondActivity.class); //經過上下文Context和SecondActivity.java類的Class對象,建立 Intent 對象 startActivity(intent);//調用系統Framework 層提供的方法,啓動 SecondActivity。
二、隱式啓動
若 SecondActivity 在AndroidManifest.xml文件中配置 intent-filter 的 action 和 category、data,以下:
<intent-filter> <action android:name="myaction2"/> <category android:name="android.intent.category.DEFAULT"/> <category android:name="mycategory" /> </intent-filter>
那麼能夠經過以下方式啓動 SecondActivity :
Intent intent = new Intent("myaction2"); startActivity(intent);
三、默認啓動
經過桌面圖標點擊應用圖標進入程序的第一個Activity,因其啓動方式有別上述兩個方式,將其劃分爲第三類的啓動方式。 若Activity在AndroidManifest.xml文件的intent-filter的action和category,以下:
<intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter>
那麼,點擊桌面的應用圖標便可啓動Activity。
注:若是在N個Activity中都配置上述的action和category,那麼桌面會有N個應用的圖標,點擊不一樣的圖標會進入對應的Activity。
Activity 的生命週期以下圖:
(1) onCreate
表示Activity正在被建立,這是第一個執行的方法,在Activity的生命週期中只執行一次。在這個方法中作一些初始化工做,好比調用setContentView去加載界面佈局,初始化Activity所須要的數據等。後續調用onStart()。
(2) onRestart
表示Activity正在從新啓動,通常狀況下,當前的Activity從不可見的狀態變爲可見狀態時,onRestart就會被調用。這種情形通常是用戶操做出現所致,好比用戶按Home鍵回到桌面或者用戶打開了一個新的Activity,這時候Activity就會暫停,接着用戶又回到該Activity。後續調用onStart()。
(3) onStart
表示Activity正在被啓動,即將開始。這個時候Activity是可見的,可是尚未出如今前臺,不能和用戶進行交互。這個時候能夠理解爲Activity已經顯示出來,可是咱們還看不到。後續的方法是onResume()。
(4) onResume
表示Activity可見,而且已經出如今前臺並開始活動,能和用戶正常進行交互。須要注意的是onStart和onResume的區別,兩者都是Activity可見,可是onStart時Activity還在後臺,而onResume時Activity到了前臺了,這時候能夠開啓動畫或者獲取獨佔性設備的操做如打開相機、獲取麥克風等。
(5) onPause
表示Activity由前臺轉到後臺,正常狀況下,緊接着onStop就會被調用。這時仍然可見。若是這時候快速地回到當前Activity,那麼onResume會被調用,這類狀況屬於極端狀況,用戶操做很難重現這一場景。此時能夠作一些存儲數據,中止動畫等操做,可是注意不能太耗時,若是太耗時會影響到新的Activity的顯示。onPause是先執行完,新的Activity的onCreate纔會執行。onResume和onPause相對應。
(6) onStop
表示Activity即將中止,當前的Activity對用戶不在可見。可稍微作些重量級的回收操做。後續的操做多是onRestart或者onDestroy或者一直保持這個狀態。
(7) onDestory
表示Activity正在被銷燬,是生命週期的最後一個回調,也是隻調用一次。發生的條件是Activity自己已經執行完畢,或者系統資源不足須要回收資源將Activity銷燬。
咱們考慮以下幾類狀況: 一、當一個Toast彈出的時候,會發生回調麼? No 二、當一個AlertDialog彈出的時候,會發生回調麼? No, 若是AlertDialog獲取焦點,Activity會觸發onWindowFocusChanged回調 三、當一個PopWindow彈出的時候,會發生回調麼? No, 若是PopWindow獲取焦點,如mPopupWindow.setFocusable(true),Activity會觸發onWindowFocusChanged回調。 4.橫豎屏切換時,會形成Activity被銷燬而後從新建立。若在Activity配置android:configChanges="orientation",橫豎屏切換時,只觸發onConfigurationChanged( )回調,Activity不會被從新建立。
Activity 有四種啓動模式,不一樣的模式,對應這 Activity 對象的建立於複用策略,能夠在 Manifest 和 代碼中指定 Activity 的啓動模式。
在探究什麼是啓動模式以前要弄請幾個問題:
Android 任務棧又稱爲 Task,它是一個棧類型的數據結構:先進後出。它用於存儲咱們的 Activity 組件。
每次打開一個新的 Activity 或 退出一個 Activity 都會在任務棧的結構中添加或減小一個 Activity,一個任務棧包含了一個 Activity 集合。Android 系統能夠經過 Task 有序的管理每一個 Activity ,並決定那個 Activity 與用戶進行交互:只用在棧頂的 Activity 才能夠跟用戶進行交互。
在應用程序退出時,必須把全部任務棧中的 Activity 清除棧時,任務棧纔會被銷燬。固然任務棧能夠移動到後臺,而且保存每一個 Activity 的狀態。能夠有序的給用戶列出Activity的任務,同時也不會丟失 Activity 的信息。
應用程序中可能不止一個任務棧,某系狀況狀況下,單獨的一個 Activity 能夠獨享一個任務棧,也會存在一個任務棧的 Activity 能夠來自不一樣的 App,同一個 App 中的 Activity 可能在不一樣的任務棧當中。
在應用程序開發過程當中,通常都須要在多個 Activity 組件之間跳轉,也可能須要在本應用中打開其餘應用的可複用的 Activity。在開發過程當中須要跳轉到原來已經開啓的 Activity 實例,此時咱們但願這個 Activity 能夠被重用而不是再從新建立一個新的 Activity 實例,但根據 Android 系統的默認行爲,每次都會爲咱們建立一個新的 Activity 實例對象並添加到任務棧中,並且 Activity 的數據和信息狀態都將會被保留 。
咱們能夠在 MainActivity 中添加一個按鈕,點擊按鈕跳轉到 SecondActivity,而後在 SecondActivity 中添加兩個按鈕,點擊一個按鈕跳轉到 MainActvity,在另外一個按鈕的點擊事件中添加以下代碼:
//獲取ActivityMananger ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); //獲取任務棧 多是多個 List<ActivityManager.RunningTaskInfo> runningTasks = am.getRunningTasks(5); //獲取當前的任務棧 ActivityManager.RunningTaskInfo runningTaskInfo = runningTasks.get(0); //獲取當前任務棧中 Activity 個數,即當前沒有換存活的 Activity 實例個數。 int numRunning = runningTaskInfo.numRunning; //Log 打印信息 Log.e("SecondActivity", "numRunning" + numRunning);
上面代碼不用深究,主要目的是想說明系統默認狀況下,當前任務棧中存活的 Activity 實例個數。當咱們在 MainActvity 中點擊按鈕跳轉到 SecondActivity ,當跳轉到 SecondActivity 在點擊第一個按鈕跳轉到 MainActivity ,不斷重複這個操做。最後當跳轉的 SecondActivity 點擊第一個按鈕獲取當前任務棧中的 Activity 個數。下面是方法和其對應運行時對應結果。
這樣形成數據沉餘,重複數據太多,最終可能還會致使內存溢出(OOM)。爲解決這些問題,Android 系統提供了一套 Activity的啓動模式來修改默認的 Activity 啓動模式。
系統默認模式,每次啓動一個Activity都會從新建立一個新的實例,而無論Activity是否已經建立了一個實例。
棧頂複用模式,系統啓動時,系統會啓動當前棧頂Activity是否是要啓動的Activity,若是是則不須要建立新的Activity而直接引用這個Activity,若是不是那麼建立新的Activity。系統會回調Activity的onNewIntent()的方法。
棧內複用模式,若是棧內已經存在了一個Activity的實例,那麼Activity不會被從新建立,同時這個Activity的onNewIntent()方法會被回調,並將該Activity實例置於棧頂,原先處於該實例頂部的Activity實例會被出棧銷燬。若是是其餘程序啓動Activity,那麼它會從新建立一個任務棧。
單實例模式,是singleTask的增強版,具備singleTask全部特色,而且此種模式下Activity只有一個實例,而且只能單獨的存在一個任務棧中。
啓動模式通常分爲兩種:
Intent intent = new Intent(this, SecondActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//Flag startActivity(intent);
setFlags方法說明
//使用一個新的Task來啓動Activity,但每一個Activity都將在一個新的Task中。 Intent.FLAG_ACTIVITY_NEW_TASK //使用singleTop模式來啓動一個Activity。 Intent.FLAG_ACTIVITY_SINGLE_TOP //使用singleTask模式來啓動一個Activity。 Intent.FLAG_ACTIVITY_CLEAR_TOP //使用singleTask模式來啓動一個Activity,使用這種方式啓動Activity,當Activity啓動其餘Activity的時候,該Activity會被銷燬,不入棧。 Intent.FLAG_ACTIVITY_NO_HISTORY //方式沒法指定 SingleInstance 模式,SingleInstances 只能在 AndroidManifest.xml 中聲明。 Intent.setFlags
這裏是一些在開發中常見的業務場景頁面使用的頁面啓動模式:
做爲Android的四大組件之一,而且也是項目開發過程當中最經常使用到的,小夥伴們要深入理解,並把它靈活的運用到項目中,固然這些也是面試中會問到的最基礎問題。
PS:若是還有未看懂的小夥伴,歡迎加入咱們的QQ技術交流羣:892271582,裏面有各類大神回答小夥伴們遇到的問題哦~