Activity启动模式的理解

一、理解 Tasks and Back Stack(任务和后台堆栈)

一个 App 对应一个 Task,该app 内的所有 activity 被安排在一个后台堆栈里。
多窗口模式下:一个windows下可能由多个 Task,系统为每个窗口单独管理 Task。

当启动一个app时,系统为其启动一个Task。其它App进入后台(每个堆栈内的 acitivity处于停止状态)。注意:如果后台任务过多,系统会销毁后台活动以释放内存,活动的状态也会丢失。

二、管理任务

Android管理任务和后台堆栈的方式,如上所述,通过将所有的活动连续地放在同一任务和“后进先出”的堆栈中,对于大多数应用程序来说是非常好的,并且不必担心您的活动与任务或它们如何退出有关。

但是,您可能会决定要中断这种正常行为:

  • 也许您希望应用程序中的一个活动在启动时 启动一个新任务(而不是放在当前任务中);
  • 当启动一个活动时,你想提出它的一个现有实例,而不是在堆栈的顶部创建一个新实例;
  • 当用户离开任务时,除了根活动,,希望清除堆栈。

您可以在<activity>清单元素中使用属性,并在传递给startActivity()的意图中使用标志。

在这方面,您可以使用的主体 <activity> 属性如下:

  • taskAffinity
  • launchMode
  • allowTaskReparenting
  • clearTaskOnLaunch
  • alwaysRetainTaskState
  • finishOnTaskLaunch

您可以使用的主要意图标志是:

  • FLAG_ACTIVITY_NEW_TASK
  • FLAG_ACTIVITY_CLEAR_TOP
  • FLAG_ACTIVITY_SINGLE_TOP

三、定义启动模式

在Android中每个界面都是一个Activity,切换界面操作其实是多个不同Activity之间的实例化操作。在Android中Activity的启动模式决定了Activity的启动运行方式。

启动模式允许您定义活动的新实例如何与当前任务关联。你可以用两种方式定义不同的启动模式:

  • 使用清单文件
    当在清单文件中声明一个活动时,可以指定活动在启动时应如何与任务相关联。
  • 使用 Intent flags
    当调用 startActivity() 时,可以在意图中包含一个标志,声明新的活动如何(或是否)与当前任务相关联。

因此,如果活动A启动活动B,活动B可以在其清单中定义它应该如何与当前任务相关联(如果有的话),而且活动A也可以请求活动B应该如何与当前任务相关联。如果两个活动都定义了活动B应该如何与任务相关联,那么活动A的请求(如意图中定义的)将被授予活动B的请求(如清单中定义的)。

注意:一些启动模式 在清单文件中可用 ,但不可用作为意图的标志;同样地,一些启动模式作为 flags 可用,但在清单中不能定义。

使用清单文件

Activity启动模式设置:

<activity android:name=".MainActivity" android:launchMode="standard" />

Activity的四种启动模式:

  1. standard (默认模式)
    系统在启动的任务中创建活动的新实例并将意图路由到该任务。
    该活动可以被实例化多次,每个实例可以属于不同的任务,并且一个任务可以具有多个实例。

  2. singleTop
    如果活动的实例已经存在于当前任务的顶部,则系统通过调用其 onNewIntent()方法将意图路由到该实例,而不是创建活动的新实例。

该活动可以多次实例化,每个实例可以属于不同的任务,并且一个任务可以有多个实例(但仅当在后台堆栈顶部的活动不是活动的现有实例)。

  1. singleTask
    系统创建一个新任务并实例化新任务的根的活动。但是,如果活动的实例已经存在于单独的任务中,则系统通过调用其 onNewIntent()方法将意图路由到现有实例,而不是创建新实例。一次只能存在一个活动实例。

注意:虽然活动在一个新任务中启动,但后退按钮仍然将用户返回到先前的活动。

  1. singleInstance
    与“singleTask ”相同,只是系统没有将任何其他活动放入实例中。该活动始终是其任务的唯一成员,该活动启动的任何活动在单独的任务中打开。

在一个新栈中创建该Activity实例,并让多个应用共享改栈中的该Activity实例。一旦改模式的Activity的实例存在于某个栈中,任何应用再激活改Activity时都会重用该栈中的实例,其效果相当于多个应用程序共享一个应用,不管谁激活该Activity都会进入同一个应用中。

举例

1.standard

public class MainActivity extends AppCompatActivity {

    TextView tv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tv = findViewById(R.id.textView);
        tv.setText(this.toString());

    }
   
    // 按钮点击事件
    public void launchStandard(View view) {
        startActivity(new Intent(this, MainActivity.class));
        tv.setText(this.toString());
    }
}

输入图片说明

由此可知,这种 Standard 模式是 每次都会创建新的Activity对象,当点击返回按钮时,他会将栈顶(当前Activity)消灭,然后跳到下一层。这种模式可能大多数情况下不是我们需要的,因为对系统性能的消耗过大。

**2.singleTop **
从上面的解释中即可知道,在每次使用新的Activity时会自动检测栈顶的当前Activity是否是需要引用的Activity,如果是则直接引用此Activity,而不会创建新的Activity。

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

public class MainActivity extends AppCompatActivity {

    TextView tv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tv = findViewById(R.id.textView);
        tv.setText(this.toString());

    }

    public void launchStandard(View view) {
        startActivity(new Intent(this, SingleTopActivity.class));
        tv.setText(this.toString());

    }
}

public class SingleTopActivity extends AppCompatActivity {

    private TextView tv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_single_top);
        tv = findViewById(R.id.textView);
        tv.setText(this.toString());
    }

   @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        Toast.makeText(this,this.getClass().getSimpleName(),Toast.LENGTH_LONG).show();
    }

    public void launchSingleTop(View view) {
        startActivity(new Intent(this, SingleTopActivity.class));
        tv.setText(this.toString());
    }
}

输入图片说明

当在SingleTopActivity点击 "启动当前页面按钮" 时,不会创建新的对象,因为该Activity 处在栈顶,不会创建新的对象,但是会回调 onNewIntent() 方法。   

3.singleTask

此启动模式和singleTop在名字上即可看出区别,即singleTop每次只检测当前栈顶的Activity是否是我们需要请求创建的,而singleTask则会检测栈中全部的Activity对象,从上向下,如果检测到是我们所请求的则会消灭此Activity对象上面的对象,直接把检测到的我们需要的Activity置为栈顶。

** 4.SingleInstance**

此启动模式和我们使用的浏览器工作原理类似,我们都知道在多个程序中访问浏览器时,如果当前浏览器没有打开,则打开浏览器,否则会在当前打开的浏览器中访问。此模式会节省大量的系统资源,因为他能保证要请求的Activity对象在当前的栈中只存在一个。

上面即为Android中的四种启动模式,我们在开发Android项目时会经常使用到,巧妙设置Activity的启动模式会节省系统开销和程序运行效率。

猜你喜欢

转载自my.oschina.net/Agnes2017/blog/1806909