您当前的位置: 首页 > 学无止境 > 心得笔记 网站首页心得笔记
56_activity的启动模式
发布时间:2021-03-04 15:00:00编辑:雪饮阅读()
标准启动模式
activity在启动过程中有所谓的启动模式,默认的没有配置启动模式时候启动模式相当于:
android:launchMode="standard"
这是标准模式,配置在清单文件中对应activity标签的属性上
//属性
//standard:标准模式
//singleTop:栈顶复用模式
//singleTask:栈内复用模式
//singleInstance:单例模式
//如不设置,Activity的启动模式默认为**标准模式(standard)**
假如有两个activity,这两个activity可以互相打开另外一个activity。
那么当项目部署后第一次运行就默认产生MainActivity1,
然后假如执行如下操作
在MainActivity1中打开MainActivity1
继续在新的MainActivity1中打开MainActivity2
继续在新的MainActivity2中打开MainActivity2
则会在activity栈中形成:
MainActivity1
MainActivity1
MainActivity1
MainActivity2
MainActivity2
那么通过返回按钮,要退出整个项目回到项目没有打开之前则是需要按5次返回键(按倒序一个个退出)。
那么建立项目如
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="启动MainActivity1"
android:onClick="MainActivity1"
/>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="启动MainActivity2"
android:onClick="MainActivity2"
/>
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="我在第一个界面"/>
</LinearLayout>
activity_main2.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="启动MainActivity1"
android:onClick="MainActivity1"
/>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="启动MainActivity2"
android:onClick="MainActivity2"
/>
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="我在第二个界面"/>
</LinearLayout>
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.lunchmode">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Lunchmode">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".MainActivity2"></activity>
</application>
</manifest>
MainActivity.java:
package com.example.lunchmode;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onResume() {
//获取当前任务id(activity的id、activity栈中条目id)
System.out.println("栈MainActivity task id ="+getTaskId());
super.onResume();
}
public void MainActivity1(View view) {
Intent intent = new Intent(this,MainActivity.class);
startActivity(intent);
}
public void MainActivity2(View view) {
Intent intent = new Intent(this,MainActivity2.class);
startActivity(intent);
}
}
MainActivity2.java:
package com.example.lunchmode;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity2 extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
}
@Override
protected void onResume() {
//获取当前任务id(activity的id、activity栈中条目id)
System.out.println("栈MainActivity2 task id ="+getTaskId());
super.onResume();
}
public void MainActivity1(View view) {
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
}
public void MainActivity2(View view) {
Intent intent = new Intent(this,MainActivity2.class);
startActivity(intent);
}
}
然后部署项目到设备可以看到第一个栈条目已经产生
这里可以看到regex匹配的是unnamed-0,这是我建立的一个日志猫过滤器配置。
若要建立日志猫过滤器配置,可以在日志猫右上侧下拉中选择如下条目
这里面可以增加、删除、修改一个配置条目,由于上面源代码中日志关键字给了一个“栈”,所以这里就简单配置如下了
利用好日志过滤器并结合不断打开activity和返回按钮就可以看到如下流程
这样就验证了activity的标准启动模式
singleTop栈顶复用模式
假如上面第二个activity启动模式配置如:
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.lunchmode">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Lunchmode">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:launchMode="singleTop" android:name=".MainActivity2"></activity>
</application>
</manifest>
即栈顶复用模式,此时同样走上面标准模式的操作流程,可以发现在退出这个项目时候返回键可以少一次了。
这是因为栈顶复用模式运用到activity2上了,而操作流程最后两次操作都是activity2,那么最后一次与倒数第二次activity就产生了复用。
但是如果最后一次是activity2而倒数第二次是activity则又会和标准模式一样,需要返回键5次点击才可以退出该项目。也就是说这种模式仅仅栈顶复用,不支持跨层复用。
singleTask栈内复用模式
如果将上面activity2的启动模式修改为singleTask栈内复用模式,然后操作流程如:
MainActivity1
MainActivity1
MainActivity1
MainActivity2
MainActivity1
MainActivity2
那么按照标准模式,要退出项目需要6次返回按钮,但是这里实际只需要4次返回按钮
这是因为栈内复用的特性,在这里当第二个MainActivity2建立时会在栈历史中寻找是否有存在相同的activty,发现已经有一个MainActivity2,于是直接使用这个MainActivity2,那么此时它会将MainActivity2上层的所有activity都会被销毁。
总结下来就是复用了一个MainActivity2并且销毁了一个MainActivity1,所以只剩下4个activity了。
singleInstance单例模式
如果将上面activity2的启动模式修改为singleInstance单例模式,然后操作流程如:
MainActivity1
MainActivity1
MainActivity1
MainActivity2
MainActivity2
MainActivity1
MainActivity2
那么按照标准模式,要退出项目需要7次返回按钮,但是这里实际只需要5次返回按钮
这是因为singleInstance单例模式的特性,它会复用栈中相同的activity,并且独立建立一个栈来存储这些复用的栈的堆地址,并不在主栈中存放。这里3个MainActivity2复用之后就节约了2次返回按钮。这是纯复用,不会销毁跨层所遇到的activity栈。
关键字词:android,启动模式,activity