美文网首页Android基础知识
Activity的四种启动模式LaunchMode

Activity的四种启动模式LaunchMode

作者: 老勇 | 来源:发表于2016-09-19 21:49 被阅读81次

    launchMode在多个Activity跳转的过程中扮演着重要的角色,它可以决定是否生成新的Activity实例,是否重用已存在的Activity实例,是否和其他Activity实例公用一个task里。这里简单介绍一下task的概念,task是一个具有栈(后进先出)结构的对象,一个task可以管理多个Activity,启动一个应用,也就创建一个与之对应的task
    Activity一共有以下四种LaunchMode:
    1.standard
    2.singleTop
    3.singleTask
    4.singleInstance
    我们可以在AndroidManifest.xml配置<activity>的Android: LaunchMode属性为以上四种之一即可,如果不配置,默认是standard

    1、standard:标准模式,这也是系统的默认模式。每次启动一个Activity都会重新创建一个新的实例,不管这个实例是否已经存在。被创建的实例的生命周期符合典型情况下的生命周期,它的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实例,并且我们需要连续按后退键两次,才能回到第一个FristActivity。
    standard模式的原理如下图所示: standard模式出栈入栈示意图.png
    如图所示,每次跳转系统都会在task中生成一个新的FirstActivity实例,并且放于栈结构的顶部,当我们按下后退键时,才能看到原来的FirstActivity实例。
    这就是standard启动模式,不管栈有没有已存在的实例,都会创建新的实例。
    2、singleTop:栈顶复用模式。在这种模式下,1️⃣如果新的Activity已经位于任务栈的栈顶,注意是位于栈顶,那么此Activity不会被重新创建,同时它的onNewIntent方法会被调用,通过此方法的参数我们可以取出当前请求的信息。需要注意的是,onCreateonStartonResume不会被调用,因为它并没有发生改变。2️⃣但是如果新的Activity实例已存在但没有位于栈顶,那么新的Activity仍然会被重新创建。
    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时,系统发现存在有FirstActivity实例,但不是位于栈顶,于是重新生成一个实例,这种方式会重新新建,onCreateonStartonResume会被调用,但是onNewIntent则不会被调用。值得注意的是,当我们不按SecondAndroid的按钮而直接按back键返回到FirstActivity时,FirstActivity不会重新创建,只是把原来的重新展现,生命周期函数执行如下: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启动模式,如果发现有对应的Activity实例正位于栈顶,则重复利用,不再生成新的实例。
    3、singleTask:栈内复用模式。这是一种单实例模式,在这种模式下,只要Activity在一个栈中存在,那么多次启动此Activity都不会重新创建实例,系统会回调其onNewIntent方法。具体一点,当一个具有singleTask模式的Activity请求启动后,例如Activity A,系统首先会寻找是否存在A想要的任务栈,如果不存在,就重新创建一个任务栈,然后创建A的实例后把A放到栈中。如果存在A所需要的任务栈,这时需要看A是否在栈中有实例存在,如果有,那么系统就把A调到(在A前面的Activity实例全部出栈)栈顶并调用其onNewIntent方法,如果不存在实例,就创建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消失了,没错,在这个跳转过程中系统发现有存在的FirstActivity实例,于是不再生成新的实例,而是将FirstActivity之上的Activity实例统统出栈,将FirstActivity变为栈顶对象,显示到幕前。也许朋友们有疑问,如果将SecondActivity也设置为singleTask模式,那么SecondActivity实例是不是可以唯一呢?在我们这个示例中是不可能的,因为每次从SecondActivity跳转到FirstActivity时,SecondActivity实例都被迫出栈,下次等FirstActivity跳转到SecondActivity时,找不到存在的SecondActivity实例,于是必须生成新的实例。但是如果我们有ThirdActivity,让SecondActivity和ThirdActivity互相跳转,那么SecondActivity实例就可以保证唯一。
    这就是singleTask模式,如果发现有对应的Activity实例,则使此Activity实例之上的其他Activity实例统统出栈,使此Activity实例成为栈顶对象,显示到幕前。
    4、singleInstance:单实例模式。是一种加强的singleTask模式,它除了具有singleTask模式的所有特性外,还加强了一点,那就是此种模式的Activity只能单独地位于一个任务栈中,换句话说,比如Activity A是singleInstance模式,当A启动后,系统会为它创建一个新的任务栈,然后A独自在这个新的任务栈中,由于栈内复用的特性,后续的请求均不会创建新的Activity,除非这个独特的任务栈被系统销毁了。

    相关文章

      网友评论

      本文标题:Activity的四种启动模式LaunchMode

      本文链接:https://www.haomeiwen.com/subject/jrkgettx.html