Activity的四種啟動模式LaunchMode

launchMode在多個Activity跳轉的過程中扮演著重要的角色,它可以決定是否生成新的Activity實例,是否重用已存在的Activity實例,是否和其他Activity實例公用一個task里。這里簡單介紹一下task的概念,task是一個具有棧(后進先出)結構的對象,一個task可以管理多個Activity,啟動一個應用,也就創(chuàng)建一個與之對應的task
Activity一共有以下四種LaunchMode:
1.standard
2.singleTop
3.singleTask
4.singleInstance
我們可以在AndroidManifest.xml配置<activity>的Android: LaunchMode屬性為以上四種之一即可,如果不配置,默認是standard

1、standard:標準模式,這也是系統的默認模式。每次啟動一個Activity都會重新創(chuàng)建一個新的實例,不管這個實例是否已經存在。被創(chuàng)建的實例的生命周期符合典型情況下的生命周期,它的onCreateonStartonResume都會被調用。該模式不會調用onNewIntent方法
下面用一個例子演示一下standard模式:
<pre><code>
public class FirstActivity extends AppCompatActivity {

@Override protected void onCreate(Bundle savedInstanceState) {

 super.onCreate(savedInstanceState);   
 setContentView(R.layout.activity_first);        

// Example of a call to a native method

TextView tv = (TextView) findViewById(R.id.sample_text);  
  
tv.setText(this.toString());
    
Button button = (Button) findViewById(R.id.btn);

button.setOnClickListener(new View.OnClickListener() {            

      @Override            
      public void onClick(View v) {               
            Intent intent = new Intent(FirstActivity.this,FirstActivity.class);                
            startActivity(intent);            
      } 

      @Override
      protected void onNewIntent(Intent intent) {                  
            super.onNewIntent(intent);      
            Log.i("FirstActivity","onNewIntent called");}
    });   

}

}
</pre></code>


1.png
2.png

3.png

通過圖片可以看到,我們每次點擊按鈕都新建了不同的FirstActivity實例,并且我們需要連續(xù)按后退鍵兩次,才能回到第一個FristActivity。
standard模式的原理如下圖所示:

standard模式出棧入棧示意圖.png

如圖所示,每次跳轉系統都會在task中生成一個新的FirstActivity實例,并且放于棧結構的頂部,當我們按下后退鍵時,才能看到原來的FirstActivity實例。
這就是standard啟動模式,不管棧有沒有已存在的實例,都會創(chuàng)建新的實例。
2、singleTop:棧頂復用模式。在這種模式下,1??如果新的Activity已經位于任務棧的棧頂,注意是位于棧頂,那么此Activity不會被重新創(chuàng)建,同時它的onNewIntent方法會被調用,通過此方法的參數我們可以取出當前請求的信息。需要注意的是,onCreateonStartonResume不會被調用,因為它并沒有發(fā)生改變。2??但是如果新的Activity實例已存在但沒有位于棧頂,那么新的Activity仍然會被重新創(chuàng)建。
1??
我們在上面代碼的基礎上為<activity>指定屬性android:launchMode="singleTop",系統就會按照singleTop啟動模式處理跳轉行為。我們重復上面幾個動作,將會出現下面的現象:
同時onNewIntent會被調用,我們可以在onNewIntent中的形參Intent intent獲取一些數據做一些操作。
<pre><code>
09-19 17:51:27.013 6674-6674/xiaoyong68.com.activitylaunchmode I/FirstActivity: onNewIntent called
</pre></code>

1.png
2.png
3.png

我們看到這個結果跟standard有所不同,三個序列號是相同的,也就是說使用的都是同一個FirstActivity實例;如果按一下后退鍵,程序立即退出,說明當前棧結構中只有一個Activity實例。
singleTop模式的原理如下圖所示:

singleTop模式出棧入棧示意圖..png

正如上圖所示,跳轉時系統會先在棧結構中尋找是否有一個FirstActivity實例正位于棧頂,如果有則不再生成新的,而是直接使用。也許朋友們會有疑問,我只看到棧內只有一個Activity,如果是多個Activity怎么辦,如果不是在棧頂會如何?2??我們接下來再通過一個示例來證實一下大家的疑問。
我們再新建一個Activity命名為SecondActivity,如下:
<pre><code>
public class SecondActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_second);
    // Example of a call to a native method
    TextView tv = (TextView) findViewById(R.id.sample_text);
    tv.setText(this.toString());
    Button button = (Button) findViewById(R.id.btn);
    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(SecondActivity.this, FirstActivity.class);
            startActivity(intent);
        }
    });
}

}
</pre></code>
然后將FirstActivity中的跳轉代碼改為:
<pre><code>
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);

startActivity(intent);
</pre></code>
點擊FirstActivity中按鈕會從FirstActivity跳轉到SecondActivity,點擊SecondActivity中按鈕會從SecondActivity又會跳轉到FirstActivity。演示結果如下:

屏幕快照 2016-09-19 20.13.51.png
屏幕快照 2016-09-19 20.14.03.png
屏幕快照 2016-09-19 20.14.14.png

我們看到,兩個FirstActivity的序列號是不同的,證明從SecondActivity跳轉到FirstActivity時生成了新的FirstActivity實例。原理圖如下:

屏幕快照 2016-09-19 20.22.12.png

我們看到,當從SecondActivity跳轉到FirstActivity時,系統發(fā)現存在有FirstActivity實例,但不是位于棧頂,于是重新生成一個實例,這種方式會重新新建,onCreateonStartonResume會被調用,但是onNewIntent則不會被調用。值得注意的是,當我們不按SecondAndroid的按鈕而直接按back鍵返回到FirstActivity時,FirstActivity不會重新創(chuàng)建,只是把原來的重新展現,生命周期函數執(zhí)行如下:onRestart->onStart->onResume->onWindowFocusChanged

<pre><code>
09-19 20:31:19.914 14458-14458/xiaoyong68.com.activitylaunchmode I/FirstActivity: onRestart called.

09-19 20:31:19.918 14458-14458/xiaoyong68.com.activitylaunchmode I/FirstActivity: onStart called.

09-19 20:31:19.918 14458-14458/xiaoyong68.com.activitylaunchmode I/FirstActivity: onResume called.

09-19 20:31:19.978 14458-14458/xiaoyong68.com.activitylaunchmode I/FirstActivity: onWindowFocusChanged called.
</pre></code>
這就是singleTop啟動模式,如果發(fā)現有對應的Activity實例正位于棧頂,則重復利用,不再生成新的實例。
3、singleTask:棧內復用模式。這是一種單實例模式,在這種模式下,只要Activity在一個棧中存在,那么多次啟動此Activity都不會重新創(chuàng)建實例,系統會回調其onNewIntent方法。具體一點,當一個具有singleTask模式的Activity請求啟動后,例如Activity A,系統首先會尋找是否存在A想要的任務棧,如果不存在,就重新創(chuàng)建一個任務棧,然后創(chuàng)建A的實例后把A放到棧中。如果存在A所需要的任務棧,這時需要看A是否在棧中有實例存在,如果有,那么系統就把A調到(在A前面的Activity實例全部出棧)棧頂并調用其onNewIntent方法,如果不存在實例,就創(chuàng)建A的實例并把A壓入棧中。

在上面的基礎上我們修改FirstActivity的屬性android:launchMode="singleTask"。演示的結果如下:

FirstActivity1.png

SecondActivity1.png

FirstActivity2.png

SecondActivity2

我們注意到,在上面的過程中,FirstActivity的序列號是不變的,SecondActivity的序列號卻不是唯一的,說明從SecondActivity跳轉到FirstActivity時,沒有生成新的實例,但是從FirstActivity跳轉到SecondActivity時生成了新的實例。singleTask模式的原理圖如下圖所示:
屏幕快照 2016-09-19 21.09.05.png

在圖中的下半部分是SecondActivity跳轉到FirstActivity后的棧結構變化的結果,我們注意到,SecondActivity消失了,沒錯,在這個跳轉過程中系統發(fā)現有存在的FirstActivity實例,于是不再生成新的實例,而是將FirstActivity之上的Activity實例統統出棧,將FirstActivity變?yōu)闂m攲ο螅@示到幕前。也許朋友們有疑問,如果將SecondActivity也設置為singleTask模式,那么SecondActivity實例是不是可以唯一呢?在我們這個示例中是不可能的,因為每次從SecondActivity跳轉到FirstActivity時,SecondActivity實例都被迫出棧,下次等FirstActivity跳轉到SecondActivity時,找不到存在的SecondActivity實例,于是必須生成新的實例。但是如果我們有ThirdActivity,讓SecondActivity和ThirdActivity互相跳轉,那么SecondActivity實例就可以保證唯一。
這就是singleTask模式,如果發(fā)現有對應的Activity實例,則使此Activity實例之上的其他Activity實例統統出棧,使此Activity實例成為棧頂對象,顯示到幕前。
4、singleInstance:單實例模式。是一種加強的singleTask模式,它除了具有singleTask模式的所有特性外,還加強了一點,那就是此種模式的Activity只能單獨地位于一個任務棧中,換句話說,比如Activity A是singleInstance模式,當A啟動后,系統會為它創(chuàng)建一個新的任務棧,然后A獨自在這個新的任務棧中,由于棧內復用的特性,后續(xù)的請求均不會創(chuàng)建新的Activity,除非這個獨特的任務棧被系統銷毀了。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容