天天看點

Activity生命周期啟動方式及啟動模式

Activity的内容

Activity生命周期啟動方式及啟動模式

Activity的生命周期

Activity生命周期啟動方式及啟動模式

多個Activity互動會調用:

Activity生命周期啟動方式及啟動模式

進行橫豎屏切換時會将此activity先銷毀掉,即經曆onPause->onStop->onDestroy方法,然後重新執行此activity的onCreate->onStart->onResume方法。

在activity銷毀的時候儲存一些狀态資訊onSaveInstanceState()方法

2種啟動方式:

顯示和隐式的啟動方式,顯示啟動方式直接指定一個Activity;隐式啟動方式指定所要啟動的Action标簽,可以在AndroidManifest.xml中添加action标簽

啟動常見系統的ACTION:

Uri uri = Uri.parse("http://www.baidu.com");

intent.setData(uri);*/

startActivity(intent);

Activity之間的資料互動:

1、直接putExtra

intent.putExtra("name", "luoguofu");

intent.putExtra("age", 23)

2、使用bundle

Bundle bundle = new Bundle();

bundle.putString("name", "lgf");

bundle.putInt("age", 22);

intent.putExtras(bundle);

3、使用對象來傳遞

       需要建立一個類調用Serializable, Serializable 是序列化接口,對象如果實作這個接口的話,就是代表可以序列化,可以序列化的意思你可以這麼了解,對象可以作為位元組流進行傳輸或儲存。不用它,是不能完成資料傳遞的,intent和budle都不能攜帶對象,但能攜帶實作序列化的對象

Person person = new Person("luo", 21, "居住位址");

Bundle bundle = new Bundle();

bundle.putSerializable("person", person);

4、使用Bitmap來傳遞圖檔

其實也主要用到了Bundle

Bundle bundle = new Bundle();

Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher);

bundle.putParcelable("image",bitmap);

intent.putExtras(bundle);

startActivity(intent);

在另一個Activity中寫入:

Bitmap bitmap =intent.getParcelableExtra("image");

imageView.setImageBitmap(bitmap);

4.1實作Parcelable就是為了進行序列化,那麼,為什麼要序列化?

1)永久性儲存對象,儲存對象的位元組序列到本地檔案中;

2)通過序列化對象在網絡中傳遞對象;

3)通過序列化在程序間傳遞對象。

4.2實作序列化的方法

Android中實作序列化有兩個選擇:一是實作Serializable接口(是JavaSE本身就支援的),一是實作Parcelable接口(是Android特有功能,效率比實作Serializable接口高效,可用于Intent資料傳遞,也可以用于程序間通信(IPC))。實作Serializable接口非常簡單,聲明一下就可以了,而實作Parcelable接口稍微複雜一些,但效率更高,推薦用這種方法提高性能。

注:Android中Intent傳遞對象有兩種方法:一是Bundle.putSerializable(Key,Object),另一種是Bundle.putParcelable(Key,Object)。當然這些Object是有一定的條件的,前者是實作了Serializable接口,而後者是實作了Parcelable接口。

4.3選擇序列化方法的原則

1)在使用記憶體的時候,Parcelable比Serializable性能高,是以推薦使用Parcelable。

2)Serializable在序列化的時候會産生大量的臨時變量,進而引起頻繁的GC。

3)Parcelable不能使用在要将資料存儲在磁盤上的情況,因為Parcelable不能很好的保證資料的持續性在外界有變化的情況下。盡管Serializable效率低點,但此時還是建議使用Serializable 。

4.4應用場景

需要在多個部件(Activity或Service)之間通過Intent傳遞一些資料,簡單類型(如:數字、字元串)的可以直接放入Intent。複雜類型必須實作Parcelable接口。

5、大資料傳遞

使用bundle進行傳遞資料時,不能大于0.5M,否則會抛出TransactionTooLargeException異常

Task和back stack

當執行某項工作時,任務(task)是與使用者互相互動的activity的集合。這些activity被管理在同一個堆中(回退堆(back  stack)),在這個堆裡存放的activity是被依次打開過的。

目前的activity啟動了另外一個activity時,新的activity就被壓入堆頂并擷取焦點。前一個activity仍在堆裡,但是處于停止狀态。當activity停止時,系統會儲存它停止時使用者界面的狀态。如果使用者按下了傳回鍵,目前的activity就會從堆中被彈出(activity被銷毀了)并且先前的activity被恢複了(先前activity的UI狀态被系統記住了)。堆中的activity從不會被重新放置,隻會從堆中彈出或是壓入--activity啟動時被壓入堆中,使用者使用後退鍵從activity離開時從堆中彈出。後退堆(back  stack)本身就和“後進先出”的對象結構執行的操作一樣。圖表1展示了多個activity之間的程序,用時間軸的方式使得這些行為變得可視化,并展示了每個時間點上後退堆的情況。

Activity生命周期啟動方式及啟動模式

         圖1 在後退堆(back  stack)裡,如何添加一個新activity任務的展示。當使用者按下傳回鍵,目前的activity被銷毀,前一個被恢複。

         如果使用者繼續按下傳回鍵,後退堆(back  stack)裡的activity依次被彈出并顯示前一個activity,直到使用者回到主螢幕(或者是任務(task)開始時運作的activity)。當堆裡所有的activity都被移除時,任務(task)也就被銷毀了。

      任務(task)可以傳回到前台,是以離開時是什麼樣子的,回來時仍然是什麼樣子。例如,假設目前任務(task)(Task A)的堆裡有三個activity。使用者按下Home鍵,通過應用程式加載器開啟了一個新的應用。當主螢幕顯示時,Task A進入了背景。當新的應用開啟時,系統為新應用建立了一個屬于它的新的任務(task)(Task B)。在和新的應用發生完互動後,使用者再次回到了主螢幕并打開了先前的應用。這時,Task A回到了前台--它堆裡的三個activity都是完整的,并且堆頂部的activity被恢複。此時,使用者也可以通過回到主螢幕、點選應用圖示來啟動Task B(或者從最近應用的螢幕上選擇Task B的任務(task))。上面說的就是Android系統裡多任務處理的例子。

通過在Manifest中為activtiy注冊資訊時添加:process 即可配置設定不同的程序名;

使用activity的getTaskId()方法可以獲得目前應用程式的taskId,同一個應用程式下的不同activity預設情況下的taskId都是相同的;

檢視任務棧:

在cmd下 adb shell dumpsys activity

Activity的4中啟動模式:

你在mainfest裡申明一個activity時,你可以使用<activity>元素裡的launchMode 屬性。

         launchMode 屬性指定了關于activity如何被加載到任務(task)的說明。有四個可以指定給launchMode 屬性的不同的讀取模式:

         "standard"(預設模式)

                 預設地,系統在activity開始的任務(task)裡給它建立一個新的執行個體并把intent發送給它。該activity可以被執行個體化多次,每個執行個體都可以屬于不同的任務(task),并且一個任務(task)裡也可以有它的多個執行個體。

         "singleTop"

                在目前任務(task)的頂部,如果一個activity的執行個體已經存在了,那麼系統會通過調用該執行個體的 onNewIntent()方法來把intent發送給它,而不是再建立一個新的執行個體。activity可以被執行個體化多次,每個執行個體都可以屬于不同的任務(task),并且一個任務(task)裡也可以有它的多個執行個體(當activity處于後退堆(back stack)的頂部時,不是它的一個現有執行個體)。

                例如,假設一個任務(task)的後退堆(back stack)由根activity A和activity B、C、D組成(D在頂部)。類型D的intent到達了。如果D是預設的啟動模式"standard",那麼D的一個新執行個體被啟動了,堆裡的内容就變為A-B-C-D-D。雖然如此,但是,如果D的啟動模式是"singleTop",那麼,已存在的D的執行個體就會通過onNewIntent() 方法收到該intent,這是因為它在堆頂--堆裡的内容仍然為A-B-C-D。但是,如果類型B的intent到達,那麼即使B的啟動模式是"singleTop",系統也仍然會新執行個體化一個B的執行個體并把它添加到 堆裡。

                注意:activity的新執行個體被建立時,使用者可以通過按下傳回鍵傳回到先前的activity。但是,當一個activity已經存在的執行個體處理了一個新的intent,那麼,在一個新的intent進入onNewIntent() 方法之前,使用者不能通過按下傳回鍵傳回activity的狀态。

          "singleTask"

                系統會建立一個新的任務(task)并把activity的執行個體做為該任務(task)的根。但是,如果該activity的執行個體在一個單獨的任務(task)裡已經存在了,那麼系統會通過調用它的onNewIntent() 方法來把intent發送給它,而不是再建立一個新的執行個體。也就是說,在同一時刻,僅僅隻會存在該activity的一個執行個體。singleTask 在啟動時系統會搜尋任務棧中是否包含該activity,如果包含則調用onNewIntent()方法并将其之上棧中其他的activity全部destroy掉。

                注意:盡管在新的任務(task)裡啟動了該activity,但是按下傳回按鈕時,使用者仍然會回到先前的activity。

         "singleInstance"

                與"singleTask"類似,不一樣的是系統不會把其它的activity發送到擁有"singleInstance"啟動模式activity的任務(task)裡。以該模式啟動的activity在任務(task)隻會有一個;任何以該模式啟動的activity都會在一個單獨的任務(task)裡被打開。

         其它的例子是Android浏覽器應用,它通過在清單檔案的<activity>元素裡指定singleTask模式來申明浏覽器裡的activity都應該在它自己單獨的任務(task)裡打開。這就意味着,如果你的應用釋出了一個intent來打開網頁浏覽器,那麼它的activity不會和你的應用放置在同一個任務(task)裡。要麼是一個新的任務(task),要麼如果浏覽器已經在背景運作了,那它的任務(task)就會被帶到前台來處理該intent。