既然是安卓开发,我们就免不了和Activity打交道,因为它是前台的界面,也是android四大组件之一,那我们就来谈谈Activity的四种加载模式。
为什么要为Activity指定加载模式?
Android对Activity的管理,采用Task(即栈)来管理多个Activity,当我们启动一个应用时,Android就会为之创建了一个Task,然后启动这个应用的入口Activity。
Android的Task是一个有点麻烦的概念,因为Android并没有为Task提供API,因此开发者无法真正访问Task,只能调用Activity的getTaskId()方法来获取它所在的Task的ID。
事实上,我们可以把Task理解成Activity栈,Task以栈的样式来管理Activity,先启动的Activity被放在Task栈底,后启动的Activity被放在Task栈顶。
那么Activity的加载模式,就负责管理实例化,加载Activity的方式,并可以控制Activity与Task之间的加载关系。
先看看哪四种模式:
①standard —>默认(标准)
不管Activity实例是否存在,都会创建一个新的实例装入Task。
(每次通过这种模式来启动目标Activity时,android总会为目标Activity创建一个新的实例,并将该Activity添加到目前的Task栈中。
这种模式不会启动新的Task,新的Activity将被添加到原有的Task中)
例子:10个应用程序都要调用浏览器的应用,
那么你需要创建10个浏览器对象的Activity的对象吗?
②singleTop —>栈顶单例(栈顶不会出现相邻的相同activity实例)
被跳转的Activity位于Task顶部时:
不会创建新的实例,直接复用已有的Activity实例
被跳转的Activity不是位于顶部时:
创建一个新的实例,同standard模式相似
③singleTask —>栈内单例(在同一个Task内只有一个实例)
采用这种模式分三种情况:
a)如果将要启动的目标Activity不存在,系统将会创建目标Activity的实例,并将它加入Task栈顶。
b)如果将要启动的目标Activity已经位于Task栈顶,此时同singleTop模式
c)如果将要启动的目标Activity没有位于Task栈顶,系统将会把位于该Activity上面的所有Activity移除Task栈,从而使得目标Activity转入栈顶。
④singleInstance —->全局单例(会单独拥有一个栈)
采用这种模式启动目标Activity时,可分为如下两种情况:
a)如果将要启动的目标Activity不存在,系统会先创建一个全新的Task,在创建目标Activity的实例,并将它加入新的Task的栈顶。
b)如果将要启动的目标Activity已经存在,无论它位于哪个应用程序中,无论它位于哪个Task中,系统会把该Activity所在的Task转到前台,从而使用该Activity显示出来。
需要指出:采用单例模式加载Activity总是位于Task栈顶,
采用单例模式加载Activity所在Task只包含该Activity
那如何设置呢??
这些启动模式可以在功能清单文件AndroidManifest.xml中进行设置,中的launchMode属性。
相关的代码中也有一些标志可以使用,比如我们想只启用一个实例,则可以使用 Intent.FLAG_ACTIVITY_REORDER_TO_FRONT 标志,这个标志表示:如果这个activity已经启动了,就不产生新的activity,而只是把这个activity实例加到栈顶来就可以了。
Intent intent = new Intent(ReorderFour.this, ReorderTwo.class); intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); startActivity(intent);
核心的Intent Flag有:
FLAG_ACTIVITY_NEW_TASK
FLAG_ACTIVITY_CLEAR_TOP
FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
FLAG_ACTIVITY_SINGLE_TOP
大家看这张图应该能够明白栈的含义(画的有点丑):
我在这里就简单做点示例:
public class AActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_a);
}
public void goAActivity(View view) {
Intent intent = new Intent(AActivity.this,BActivity.class);
}
}
activity_a.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.briup.lauchmodetest.AActivity">
<Button
android:onClick="goAActivity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="跳转到AActivity"/>
</RelativeLayout>
public class BActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_b);
}
public void goBActivity(View view) {
Intent intent = new Intent(BActivity.this,AActivity.class);
}
}
activity_b.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.briup.lauchmodetest.AActivity">
<Button
android:onClick="goBActivity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="跳转到BActivity"/>
</RelativeLayout>
①现在我们假设 A 跳到 B ,然后 B 跳到 B,再 B 跳到 A,都采用默认的加载模式,栈的情况是怎么样的呢
②现在我们假设 A 跳到 B ,然后 B 跳到 B,再 B 跳到 A,B采用栈顶单例加载模式,栈的情况是怎么样的呢
③现在我们假设 A 跳到 B ,然后 B 跳到 B,再 B 跳到 A,B采用栈内单例加载模式,栈的情况是怎么样的呢
④现在我们假设 A 跳到 B ,然后 B 跳到 B,再 B 跳到 A,B采用全局单例加载模式,栈的情况是怎么样的呢
大家有没有理解呢,去试试吧,有什么不懂可以在下方提问或者和我一起探讨。