美文网首页
Activity 的4种启动模式

Activity 的4种启动模式

作者: 95大白菜 | 来源:发表于2017-05-12 19:06 被阅读27次

在这里借助简书平台作为学习的笔记,接下来的内容,可能对即将步入职场,Android 面试有些帮助

standard

standard 是activity 默认的启动方式,我们知道,Android 是使用返回栈来管理活动的,每当启动一个新的活动,它都会创建一个该活动的实例,返回栈中,并处于栈顶。而且在创建该活动的实例时,它不会在乎栈中是否存在了这个activity的实例
接下来给大家一段实例

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.e("MainActivity",this.toString());
        setContentView(R.layout.activity_main);

        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this,MainActivity.class);
                startActivity(intent);
            }
        });
    }
}

嗯?为什么是跳转到MainActivity ?莫慌,我们这段代码其实没什么意义,但是它是我们用于查看栈中的活动实例用的

1.png

这个时候我们会发现,当我们点击button的时候,后台打印了activity的实例,我们需要连续按两次back键才能完全退出程序,给大家画个模型图(出入栈的规则为:先入后出)

2.png

singleTop

其实,如果我们考虑优化的问题,栈内存在多个相同的实例(区别是地址不同),是不怎么合理的,所以singleTop模式就是来解决这样的问题的(其实并没有完全解决,下面会聊到),当该活动处于栈顶的时候,且启动模式为singleTop就不会再创建该活动的实例,而是直接使用它。

<activity android:name=".MainActivity"
            android:launchMode="singleTop"
            >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

在对应的activity 中添加这行代码android:launchMode="singleTop" 然后,你在打印台后面,无论你点击BUTTON多少次,后台都只有一个MainActivity 的实例,当然它的前提条件是该activity在栈中的实例必须是处于栈顶,然后你只要按一次back键,就会退出程序了

3.png

为了方便理解,再创建一个activity,并且命名为TestActivity,然后修改MainActivity 中的Intent 的内容,让其指定跳转到TestActivity ,然后我们再给出TestActivity 的代码内容

public class TestActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.e("TestActivity",this.toString());
        setContentView(R.layout.activity_test);

        Button button2 = (Button) findViewById(R.id.button2);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(TestActivity.this,MainActivity.class);
                startActivity(intent);
            }
        });
    }
}
4.png

你会发现,再第一次跳转之后,MainActivity 已经不处于栈顶了,所以再TestActivity 的页面中,我们在点击BUTTON2 的时候,它跳转到MainActivity 时,它是重新创建了MainActivity 的实例的。要退出程序时就要连续按三次back键了

singleTask

行了,其实这时候也发现了问题,如果activity 的实例没有栈顶,而栈中有存在了该activity 的实例那么是否会很浪费内存,(如果你对按返回键时的顺序没要求的话)那么这个时候singleTask 就派上用场了,当我们指定activity 的启动模式为singleTask 的时候,每次我们启动该activity时,系统都会先检测栈中是否存在该activity 的实例,如果有则直接使用该实例,并把该活动以上的所有活动都出栈,没有的话就重新创建该活动实例
用代码来验证一下,在 mainfests 的配置文件中将MainActivity 的android:launchMode="singleTop" 改为android:launchMode="singleTask"

这个时候我们在MainActivity 添加生命周期中的某个片段 onRestart() ,在TestActivity 中添加onDestory(),(希望提到这你能马上想到activity 的生命周期,因为这很多公司在面试的时候基本都会提问的,算了,自己在写这篇笔记的时候也没能马上想起,所以activity的生命周期为:onCreate(),onStart(),onResume(),onPause(),onStop(),onDestory(),onRestart())。
行了,这个时候再给出MainActivity 和TestActivity的代码
MainActivity 代码

public class MainActivity extends AppCompatActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      Log.e("MainActivity",this.toString());
      setContentView(R.layout.activity_main);

      Button button = (Button) findViewById(R.id.button);
      button.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v) {
              Intent intent = new Intent(MainActivity.this,TestActivity.class);
              startActivity(intent);
          }
      });
  }
  protected void onRestart(){
      super.onRestart();
      Log.e("MainActivity","onRestart");
  }
}

TestActivity代码

public class TestActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.e("TestActivity",this.toString());
        setContentView(R.layout.activity_test);

        Button button2 = (Button) findViewById(R.id.button2);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(TestActivity.this,MainActivity.class);
                startActivity(intent);
            }
        });
    }
    protected void onDestroy(){
        super.onDestroy();
        Log.e("TestActivity","onDestroy");
    }
}

在启动MainActivity之后,便创建了一个MainActivity实例,点击BUTTON 之后,创建了TestActivity 的实例,这个时候MainActivity 在栈中的位置已经不是在栈顶了,我们在TestActivity 中点击BUTTON2 跳回MainActivity ,这个时候MainActivity 调用了onRestart()方法,而之前在MainActivity 的TestActivity 的实例已经出栈了,所以TestActivity 执行了onDestory() 方法

6.png 5.png

singleInstance

singleInstance 是稍微比较复杂的,其应用场景是该程序要和其他程序要共享某个Activity 实例时,我们知道每个程序都有自己的返回栈,同一个活动若要在不同的返回栈中,那么就得创建新的实例,而singleInstance模式正是解决这种问题的,在该模式下,会为activity 单独创建一个返回栈,其他程序想用到该activity的都会在同一个返回栈中使用它,我们先把TestActivity 的启动模式修改为singleInstance,修改MainActivity和TestActivity 中log 里的内容,
MainActivity

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.e("MainActivity","栈的ID"+getTaskId());
        setContentView(R.layout.activity_main);

        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this,TestActivity.class);
                startActivity(intent);
            }
        });
    }

TestActivity

 protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.e("TestActivity","栈的ID"+getTaskId());
        setContentView(R.layout.activity_test);

        Button button2 = (Button) findViewById(R.id.button2);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(TestActivity.this,DemoActivity.class);
                startActivity(intent);
            }
        });
    }

DemoActivity

  protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.e("DemoActivity","栈ID"+getTaskId());
        setContentView(R.layout.activity_demo);
    }

然后你可以看看MainActivity ,TestActivity和DemoActivity 的栈ID,你会发现,MainActivity 和 DemoActivity 的栈ID 是一样的 !如果我们要退出程序,我们在按一次back键时,我们会发现我们是由DemoActivity 跳转到了MainActivity,如果我们再按back 键,会由MainActivity 跳转到TestActivity ,再按一次back 键,才能彻底的退出程序,也就是当我们所有栈中的实例都清空时才能退出程序


7.png

也可以关注一下我的公众号,不定期的发推送一些文章

95大白菜.jpg

相关文章

网友评论

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

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