Android Activity的启动模式(一)

Android Activity的启动模式(一)

Activity的四种LaunchMode

standard:标准模式

    standard是系统的默认启动模式,每次启动一个Activity都会重新创建一个实例,不管这个实例是否已经存在。这是一种典型的多实例实现,一个任务栈可以有多个实例,每个实例也可以属于不同的任务栈,在这种模式下,谁启动了这个Activity,那么这个Activity就运行在谁的Activity所在的栈中。

比如:ActivityA 启动了Activity B(B是标准模式),那么B就会进入到A所在的栈中。

这样就出现一个很容易忽视的问题,当我们用ApplicationContext去启动一个standard模式的Activity时,会出现如下错误:

@Override
protected void onCreate(Bundle savedInstanceState) {
     
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Log.i(TAG, "this is onStart");
    mContext = getApplicationContext();
    Intent intent = new Intent(this, SecondActivity.class);
    mContext.startActivity(intent);
}
Caused by: android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity  context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
        at android.app.ContextImpl.startActivity(ContextImpl.java:1018)
        at android.app.ContextImpl.startActivity(ContextImpl.java:994)
        at android.content.ContextWrapper.startActivity(ContextWrapper.java:403)
        at com.org.tcl.launchmodetest.MainActivity.onCreate(MainActivity.java:22)

这是因为standard模式的Activity默认会进入启动它的Activity所属的任务栈中,但是由于非Activity类型的Context并没有所谓的任务栈,所以这就会报出错误。

解决这个问题的方法很简单,启动这个Activity的时候指定FLAG_ACTIVITY_NEW_TASK标记位,这样在启动这个Activity的时候就会为它创建一个新的任务栈,这就没问题了。

 @Override
 protected void onCreate(Bundle savedInstanceState) {
     
     super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_main);
     Log.i(TAG, "this is onCreate");
     mContext = getApplicationContext();
     Intent intent = new Intent(this, SecondActivity.class);
     intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
     mContext.startActivity(intent);
 }

SingleTop:栈顶复用模式

    栈顶复用模式,顾名思义,在这种模式下:

    1. 如果新的Activity已经位于任务栈的栈顶,那么此Activity不会被重新创建,同时它得onNewIntent方法会被回调,通过此方法的参数我们可以取出当前请求的信息,需要注意的是,这个Activity的onCreate、onStart不会被系统调用,因为它并没有发生改变。

    2. 如果新Activity的实例已经存在但是不是位于栈顶,那么新的Activity仍然会被重建

    举个例子,假设目前栈内的情况为ABCD,其中ABCD为4个Activity,A在栈底,D在栈顶,那么假设要再次启动D,如果D的启动模式是SingleTop,那么栈内情况还是ABCD,如果D的启动模式是standard,那么栈内情况就变成了ABCDD

SingleTask:栈内复用模式

    栈内复用模式,这是一种单实例模式,在这个模式下,只要Activity在一个栈中存在,那么多次启动这个Activity都不会重新创建实例。和SingleTop一样,这个也会调用onNewIntent方法。

    具体一点说,当一个具有singletask模式的Activity A请求启动后,系统首先会寻找是否存在A想要的任务栈,如果不存在,就会重新创建一个任务栈,然后创建A的实例并将A放到这个栈中;如果存在A想要的任务栈,这时需要看A是否在栈中有实例存在,如果有实例存在,那么系统会将A调到栈顶并调用它的onNewIntent方法,如果实例不存在,就创建A的实例并把A压入栈中。

    举例说明一下:

  • 比如目前任务栈S1 中的情况是ABC,这个时候Activity D以SingleTask的模式请求启动,其所需要的任务栈是S2,由于S2和D都不存在,所以系统会先创建任务栈S2,然后再创建D的实例将D入栈到S2。
  • 另外一种情况,假设D所需要的任务栈为S1,其他情况如上,那么由于S1已经存在,系统会直接创建D并将其入栈到S1中。
  • 如果D所需的任务栈为S1,并且当前任务栈S1的情况为ADBC,那么根据栈内复用原则,此时D不会创建,系统会把D切换到栈顶并调用其onNewIntent方法,同时由于SingleTask默认具有clearTop的效果,会导致栈内所有在D上面的Activity全部出栈,于是最终S1中的情况变为AD。

SingleInstance:单实例模式

    单实例模式:这是一种加强的SingleTask模式,它除了具有SingleTask模式的所有特性之外,还加强了一点,那就是具有此种模式的Activity只能单独的位于一个任务栈中,换句话说,如果Activity A是SingleInstance模式,当A启动后,系统会它创建新的任务栈,然后A独立的在这新的任务栈中,由于栈内复用的特性,后续的请求均不会创建新的Activity,除非这个特性的任务栈已经被系统销毁了。

你可能感兴趣的:(Android,UI,android)