Activity 四种启动模式

作者: CaostGrace | 来源:发表于2018-02-25 11:31 被阅读0次

    前言

    当我们启动安卓应用程序时,就会对应的启动这个应用程序对应的入口Activity,而这个Activity又可以启动很多个不同的Activity,系统通过任务栈来管理这些被启动Activity,栈是一种先进后出的的数据集合,每次创建一个Activity实例,系统都会将这个实例压入对应的任务栈顶,假如要是多次启动同一个Activity的话,对应的任务栈内就被压入多个此Activity的实例,造成极大的内存浪费。这种做法显然不合理,对此Android提供四种Activity启动模式来修改系统这一默认行为。这四种启动模式分别为:standardsingleTopsingleTasksingleInstance。配置形式:android:launchMode="standard / singleTop / singleTask / singleInstance",这里我们逐一对四种启动模式进行讲解。

    standard

    standard 即标准模式,这是系统的默认启动模式,在不指定启动模式的情况下,系统默认使用此模式启动Activity。当使用这个模式的时候,每启动一个Activity都会重复创建一个此Activity的实例,而不管当前任务栈中是否有此Activity的实例。

    这里我们新建立一个StandardActivity 类,配置启动模式为standard ,在布局文件当中添加一个按钮控件,并在StandardActivity中添加这个按钮响应点击事件的方法,里面代码为从自身跳转到自身的代码,然后在onCreate方法中加上打印hashCode的日志。

    <activity android:name=".StandardActivity" android:launchMode="standard"/>
    
    Log.i("==onCreate==","StandardActivity hashCode: "+ StandardActivity .this.hashCode());
    
    Intent intent = new Intent(this,StandardActivity.class);
    startActivity(intent);
    
    1.png 输出日志如下: 2.png

    从日志可见每次启动的Activity的实例都不是同一个,也就是在该模式下,每次启动同一个Activity,都会重复创建此Activity的实例对象。

    singleTop

    singleTop 即栈顶单一实例模式,在设置了此模式的情况下,如果栈顶有被启动的Activity的实例,那么这个Activity不会再次创建新的实例压入栈顶,而是调用栈顶实例的onNewIntent 方法传入构建的Intent对象,实现Activity的复用,如果栈顶没有此Activity的实例,则创建此Activity的实例压入栈顶。

    新建SingleTopActivity类,清单文件此Activity添加launchMode为singleTop,布局文件添加按钮,按钮的点击事件中实现自己跳转自己的代码,在onCreate方法中添加打印日志。重写onNewIntent方法,里面添加打印日志的代码。新建FristActivity 类作为程序的入口类,里面添加跳转到SingleTopActivity的代码逻辑。

    <activity android:name=".SingleTopActivity" android:launchMode="singleTop"/>
    

    SingleTopActivity类:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_singletop);
        Log.i("==onCreate==","SingleTopActivity hashCode: "+SingleTopActivity.this.hashCode());
    }
    
    // 按钮点击事件
    public void goToMySelf(View view) {
        Intent intent = new Intent(this,SingleTopActivity.class);
        startActivity(intent);
    }
    
    @Override
    protected void onNewIntent(Intent intent) {
        Log.i("==onNewIntent=="," SingleTopActivity-onNewIntent hashCode: "+SingleTopActivity.this.hashCode());
        super.onNewIntent(intent);
    }
    
    

    FristActivity 类:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_frist);
        Log.i("==onCreate==","FristActivity hashCode: "+ FristActivity.this.hashCode()+"");
    }
        
    public void goToSingleTopActivity(){
        Intent intent = new Intent(this,SingleTopActivity.class);
        startActivity(intent);
    }
    

    这里首先启动FristActivity ,然后启动SingleTopActivity,启SingleTopActivity后,再次从SingleTopActivity本身启动了两次SingleTopActivity,然后返回至FristActivity再次启动SingleTopActivity后,从日志当中可以看出,当SingleTopActivity处于栈顶的时候,再次启动SingleTopActivity 它的hashCode值是一样的,回调的是onNewIntent方法而不是onCreate方法,当返回至FristActivity时,FristActivity就处于栈顶,再次启动SingleTopActivity后,因为当前栈顶实例是FristActivity ,从后面两行日志可以看出,系统就重新创建了SingleTopActivity的实例。

    日志输出: 3.png

    singleTask

    singleTask 即栈内单一实例模式,在设置了该模式的情况下,如果当前任务栈内有新启动的Activity的实例,则把这个实例移至栈顶,处于此实例上方的其他Activity实例全部移除当前任务栈,如果当前任务栈没有此实例,则创建Activity实例压入栈顶。

    新建SingleTaskActivity 和FristActivity 两个类,具体代码如下。我们从FristActivity 启动SingleTaskActivity 过后,跳转回FristActivity 再次启动SingleTaskActivity 这样循环两次。

    清单文件配置:

    <activity android:name=".SingleTaskActivity" android:launchMode="singleTask"/>
    

    SingleTaskActivity类:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_singletask);
        Log.i("==onCreate==","SingleTaskActivity hashCode: "+SingleTaskActivity.this.hashCode());
    }
    
    @Override
    protected void onNewIntent(Intent intent) {
        Log.i("==onNewIntent==","SingleTaskActivity-onNewIntent hashCode: "+SingleTaskActivity.this.hashCode());
        super.onNewIntent(intent);
    }
    
    public void toFristActivity(View view) {
        Intent intent = new Intent(this,FristActivity.class);
        startActivity(intent);
    }
    
    

    FristActivity 类:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_frist);
        Log.i("==onCreate==","FristActivity hashCode: "+FristActivity.this.hashCode());
    }
    public void toSingleTaskActivity(View view) {
        Intent intent = new Intent(FristActivity.this,SingleTaskActivity.class);
        startActivity(intent);
    }
    
    
    日志输出如下: 4.png

    从日志当中可以看见,除了FristActivity的hashCode一直在变化外,SingleTaskActivity 的hashCode一直都相同,而且SingleTaskActivity只调用了一次onCreate方法,其余都是回调onNewIntent 方法实现Activity的复用。由于每次需要跳转到FristActivity,导致SingleTaskActivity的实例被多次压入FristActivity实例的下方,由此可以证明在当前任务栈如果存在设置了singleTask启动模式的Activity实例,那么当再次启动此Activity时会回调onNewIntent方法实现Activity的复用。

    singleInstance

    singleInstance 即全局单例模式,该模式比较特殊,它具有singleTask模式的全部特性,同时设置启动模式为此模式的Activity只能单独位于一个任务栈中,也就是它不与其他Activity实例共用一个任务栈,而是自己独占一个任务栈,整个系统之中就此一个实例。当设置了此模式的新的Activity被启动时,如果当前系统中有此Activity实例的任务栈,系统就重用此实例,如果系统中没有此Activity实例的任务栈,则重新创建一个新的任务栈然后把此Activity的实例压入栈中。

    新建FristActivity类和SingleInstanceActivity类。然后新建一个项目,里面添加一个可以通过隐式跳转到SingleInstanceActivity的按钮的点击事件。首先启动本应用的FristActivity类,跳转到SingleInstanceActivity中,然后再次跳转到FristActivity后,再重新跳转回SingleInstanceActivity,然后打开新建的app,跳转到SingleInstanceActivity中。

    清单文件配置:

    <activity android:name=".SingleInstanceActivity" android:launchMode="singleInstance"/>
    

    本应用的SingleInstanceActivity 类:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_singleinstance);
        Log.i("==onCreate==","SingleInstanceActivity hashCode: "+SingleInstanceActivity.this.hashCode());
    }
    @Override
    protected void onNewIntent(Intent intent) {
        String data = intent.getStringExtra("result");
        Log.i("==onNewIntent==","SingleInstanceActivity-onNewIntent hashCode: "+this.hashCode()+"data:"+data);
        super.onNewIntent(intent);
    }
    public void toFristActivity(View view) {
        Intent intent = new Intent(this,FristActivity.class);
        startActivity(intent);
    }
    

    本应用的FristActivity 类:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_frist);
        Log.i("==onCreate==","FristActivity hashCode: "+FristActivity.this.hashCode());
    }
    public void toSingleTaskActivity(View view) {
        Intent intent = new Intent(this,SingleInstanceActivity.class);
        intent.putExtra("result","本身应用的FristActivity跳转过来");
        startActivity(intent);
    }
    
    

    另外一个应用,具备跳转到SingleInstanceActivity方法的MainActivity 类:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.i("==新app-MainActivity==","MainActivity hashCode: "+this.hashCode());
    }
    
    public void toSingleInstanceActivity(View view) {
        Intent intent = new Intent("SingleInstanceActivity");
        intent.putExtra("result","新的应用APP跳转过来");
        startActivity(intent);
    }
    
    
    日志输出如下: 5.png

    从日志当中可以看出,当第一次从FristActivity跳转至SingleInstanceActivity时调用了SingleInstanceActivity的onCreate方法,第二次从FristActivity跳转至SingleInstanceActivity时,调用了onNewIntent方法,实现了SingleInstanceActivity的复用,并打印日志说明是从本身应用跳转的,然后打开新建的应用跳转至SingleInstanceActivity时,依旧是调用的onNewIntent方法,而不是onCreate方法,并且在日志中也显示出是从新建的app跳转至SingleInstanceActivity,由此可以说明在设置了singleInstance模式的情况下,启动此Activity后,全局就此一个实例,并且独占一个任务栈。

    到此Activity的四种启动模式就讲完了,其中有什么不足的地方还望大家指正。

    相关文章

      网友评论

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

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