ps:本文系转载文章,阅读原文可获取源码,文章末尾有原文连接java
ps:本文的 demo 是用 kotlin 语言写的android
Activity的标志位Flags有不少,可是咱们在实际开发中用到的并很少,经常使用的且能够设定Activity 启动模式的有 Intent.FLAG_ACTIVITY_CLEAR_TOP、Intent.FLAG_ACTIVITY_NEW_TASK、Intent.FLAG_ACTIVITY_SINGLE_TOP 和 Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;下面对它们一一介绍。app
一、Intent.FLAG_ACTIVITY_CLEAR_TOPide
具备标记位的 Activity,当它启动时,若是它的实例已经存在,那么在同一个任务栈中位于它之上的全部 Activity 统统都要出栈;该模式不少状况下是和 Intent.FLAG_ACTIVITY_NEW_TASK 一块儿使用的,在这样的状况下,若是被启动 Activity 的实例若是已经存在,那么系统会调用它的 onNewIntent 方法。若是被启动的 Activity 用的是 standard 模式启动且被启动的 Activity 之上还有其余的 Activity,那么它连同它之上的Activity都要出栈,系统会建立新的Activity实例并放入栈顶。下面对其进行举个例子:函数
(1)新建一个 kt 文件 FlagActivityClearTopActivity:this
class FlagActivityClearTopActivity : AppCompatActivity() {日志
var TAG: String = "Activity" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_flag_clear_top) Log.d(TAG,"----------FlagActivityClearTopActivity---onCreate") } fun startTwoFlagActivityClearTopActivity() { var intent: Intent = Intent(this,TwoFlagActivityClearTopActivity::class.java) startActivity(intent) } override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) Log.d(TAG,"----------FlagActivityClearTopActivity---onNewIntent") } fun onClick(v: View) { startTwoFlagActivityClearTopActivity() } override fun onDestroy() { super.onDestroy() Log.d(TAG,"----------FlagActivityClearTopActivity---onDestroy") }
}code
(2)新建一个 xml 文件 activity_flag_clear_top:xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout图片
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.xe.demo.flagsdemo.FlagActivityClearTopActivity"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="当前界面是 FlagActivityClearTopActivity"/> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="onClick" android:textAllCaps="false" android:text="启动 TwoFlagActivityClearTopActivity"/>
</LinearLayout>
(3)新建一个 kt 文件 TwoFlagActivityClearTopActivity:
class TwoFlagActivityClearTopActivity : AppCompatActivity() {
var TAG: String = "Activity" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_two_flag_clear_top) } fun onClick(v: View) { if (v.id == R.id.btn_flag_activity_clear_top) { var intent: Intent = Intent(this, FlagActivityClearTopActivity::class.java) intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) startActivity(intent) } else if (v.id == R.id.btn_flag_activity_clear_top_and_flag_activity_single_top) { var intent: Intent = Intent(this, FlagActivityClearTopActivity::class.java) var flag: Int = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP intent.setFlags(flag) startActivity(intent) } } override fun onDestroy() { super.onDestroy() Log.d(TAG,"----------TwoFlagActivityClearTopActivity---onDestroy") }
}
(4)新建一个 xml 文件 activity_two_flag_clear_top:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.xe.demo.flagsdemo.TwoFlagActivityClearTopActivity"> <TextView android:layout_width="match_parent" android:text="当前页面是 TwoFlagActivityClearTaskActivity" android:layout_height="wrap_content" /> <Button android:id="@+id/btn_flag_activity_clear_top" android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="onClick" android:textAllCaps="false" android:text="以Intent.FLAG_ACTIVITY_CLEAR_TOP方式启动 FlagActivityClearTaskActivity"/> <Button android:id="@+id/btn_flag_activity_clear_top_and_flag_activity_single_top" android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="onClick" android:textAllCaps="false" android:text="以Intent.FLAG_ACTIVITY_CLEAR_TOP和Intent.FLAG_ACTIVITY_SINGLE_TOP方式启动 FlagActivityClearTaskActivity"/>
</LinearLayout>
运行起来以后,它们有2种操做步骤
第一种操做步骤,一开始运行时出现这个主界面:
图片
点击“启动 TwoFlagActivityClearTopActivity”按钮后跳转以下界面:
图片
当点击“以Intent.FLAG_ACTIVITY_CLEAR_TOP方式启动 FlagActivityClearTaskActivity”按钮时,跳转到程序一开始运行的主界面,并打印以下日志:
图片
第二种操做步骤,一开始运行时出现这个主界面:
图片
点击“启动 TwoFlagActivityClearTopActivity”按钮后跳转以下界面:
图片
当点击“以Intent.FLAG_ACTIVITY_CLEAR_TOP和Intent.FLAG_ACTIVITY_SINGLE_TOP方式启动 FlagActivityClearTaskActivity”按钮时,跳转到程序一开始运行的主界面,并打印以下日志:
图片
Intent.FLAG_ACTIVITY_CLEAR_TOP 总结:第一种操做步骤,FlagActivityClearTopActivity 实例已经存在,再次启动 FlagActivityClearTopActivity 时,会把 FlagActivityClearTopActivity 之上的 Activity 弹出来并从新建立一个 FlagActivityClearTopActivity 实例;第二种操做步骤,FlagActivityClearTopActivity 实例已经存在,再次启动 FlagActivityClearTopActivity 时,会把 FlagActivityClearTopActivity 之上的 Activity 弹出来但不会从新建立 FlagActivityClearTopActivity 实例,只是调用它的 onNewIntent 方法。
二、Intent.FLAG_ACTIVITY_NEW_TASK
在Activity上下文以外启动 Activity 须要给 Intent 设置FLAG_ACTIVITY_NEW_TASK 标志,也就是说把将要启动的 Activity 放在一个新栈中,否则会报异常;加了该标志,若是在同一个应用中进行 Activity 跳转,不会建立新的 Task,只有在不一样的应用中跳转才会建立新的 Task。
下面举个例子(用 Java 代码写的),该例子 demo 是安卓4.4的手机上运行的:
(1)新建一个 MainActivity 类:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
}
public void onClick(View v) {
Context context = getApplicationContext(); Intent intent = new Intent(this,Main2Activity.class); //当添加这一行代码时,程序就能够正常运行
// intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true;
}
}
(2)新建一个 activity_main.xml 文件:
<LinearLayout 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" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:orientation="vertical" tools:context=".MainActivity" > <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="启动Main2Activity" android:onClick="onClick"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="MainActivity" />
</LinearLayout>
(3)新建一个 Main2Activity 类:
public class Main2Activity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main2, menu); return true;
}
}
(4)新建一个 activity_main2.xml 文件:
<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" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".Main2Activity" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Main2Activity" />
</RelativeLayout>
当程序运行起来时,我点击“启动Main2Activity”就报以下错误:
图片
三、Intent.FLAG_ACTIVITY_SINGLE_TOP
这个标志位的做用是为 Activity 指定 “singleTop” 启动模式,其效果和在 AndroidManifest.xml 中指定该启动模式相同。
下面咱们来举个例子,只是验证 “singleTop” 启动模式的一部分“栈顶复用”:
(1)新建一个 kt 文件 FlagActivitySingleTopActivity:
class FlagActivitySingleTopActivity : AppCompatActivity() {
var TAG: String = "Activity" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_flag_single_top) } override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) Log.d(TAG,"-------FlagActivitySingleTopActivity---onNewIntent") } fun onClick(v: View) { var intent: Intent = Intent(this,FlagActivitySingleTopActivity::class.java) intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP) startActivity(intent) }
}
(2)新建一个 xml 文件 activity_flag_single_top:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.xe.demo.flagsdemo.FlagActivitySingleTopActivity"> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="onClick" android:text="点击改按钮启动本身"/>
</LinearLayout>
运行后以下所示:
图片
当点击“点击改按钮启动本身”时,界面没有发生任何改变,可是却打印了以下日志:
图片
四、Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
若是新活动已在任务中,用该标志位启动并不会从新建立它,而是将它移到任务的历史栈的前面,它等同于在 AndroidManifest.xml 中指定 Activity 的属性 android:excludeFromRecents="true"。
咱们来举个例子:
(1)新建一个 kt 文件 FlagActivityReorderToFrontActivity :
class FlagActivityReorderToFrontActivity : AppCompatActivity() {
var TAG:String = "Activity" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_flag_reorder_to_front) } override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) Log.d(TAG,"-------FlagActivityReorderToFrontActivity---onNewIntent") } override fun onResume() { super.onResume() Log.d(TAG,"-------FlagActivityReorderToFrontActivity---onResume") } override fun onDestroy() { super.onDestroy() Log.d(TAG,"-------FlagActivityReorderToFrontActivity---onDestroy") } fun onClick(v: View) { var intent: Intent = Intent(this,TwoFlagActivityReorderToFrontActivity::class.java) startActivity(intent) }
}
(2)新建一个 xml 文件 activity_flag_reorder_to_front :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.xe.demo.flagsdemo.FlagActivityReorderToFrontActivity"> <TextView android:layout_width="match_parent" android:text="当前界面是 FlagActivityReorderToFrontActivity" android:layout_height="wrap_content" /> <Button android:layout_width="match_parent" android:onClick="onClick" android:textAllCaps="false" android:text="启动 TwoFlagActivityReorderToFrontActivity" android:layout_height="wrap_content" />
</LinearLayout>
(3)新建一个 kt 文件 TwoFlagActivityReorderToFrontActivity :
class TwoFlagActivityReorderToFrontActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_two_flag_reorder_to_front) } fun onClick(v: View) { var intent: Intent = Intent(this,FlagActivityReorderToFrontActivity::class.java) intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) startActivity(intent) }
}
(4)新建一个 xml 文件 activity_two_flag_reorder_to_front :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.xe.demo.flagsdemo.TwoFlagActivityReorderToFrontActivity"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="当前界面是 TwoFlagActivityReorderToFrontActivity"/> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:textAllCaps="false" android:onClick="onClick" android:text="启动 FlagActivityReorderToFrontActivity"/>
</LinearLayout>
程序刚开始运行时,效果图以下所示:
图片
当点击“启动 TwoFlagActivityReorderToFrontActivity”按钮时,跳转到以下界面:
图片
当点击“启动 FlagActivityReorderToFrontActivity”按钮时,又跳转到以下界面并打印出日志:
图片
图片
到了这一步以后,这个 APP 里其实并无2个 FlagActivityReorderToFrontActivity 界面,只有一个 FlagActivityReorderToFrontActivity;从日志里能够看出,FlagActivityReorderToFrontActivity 的 onDestroy 函数没有执行,只执行了 onResume 和 onNewIntent 函数,说明了该 Activity 并无从新建立,只是将它切换到栈顶而已。