关于java:Android中Activity的Flags

51次阅读

共计 11740 个字符,预计需要花费 30 分钟才能阅读完成。

ps:本文系转载文章,浏览原文可获取源码,文章开端有原文链接

ps:本文的 demo 是用 kotlin 语言写的

Activity 的标记位 Flags 有很多,然而咱们在理论开发中用到的并不多,罕用的且能够设定 Activity 启动模式的有 Intent.FLAG_ACTIVITY_CLEAR_TOP、Intent.FLAG_ACTIVITY_NEW_TASK、Intent.FLAG_ACTIVITY_SINGLE_TOP 和 Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;上面对它们一一介绍。

1、Intent.FLAG_ACTIVITY_CLEAR_TOP

具备标记位的 Activity, 当它启动时,如果它的实例曾经存在,那么在同一个工作栈中位于它之上的所有 Activity 统统都要出栈;该模式很多状况下是和 Intent.FLAG_ACTIVITY_NEW_TASK 一起应用的,在这样的状况下,如果被启动 Activity 的实例如果曾经存在,那么零碎会调用它的 onNewIntent 办法。如果被启动的 Activity 用的是 standard 模式启动且被启动的 Activity 之上还有其余的 Activity,那么它连同它之上的 Activity 都要出栈,零碎会创立新的 Activity 实例并放入栈顶。上面对其进行举个例子:

(1)新建一个 kt 文件 FlagActivityClearTopActivity:

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")
}

}

(2)新建一个 xml 文件 activity_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.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 办法。

2、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”就报如下谬误:

图片

3、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>

运行后如下所示:

图片

当点击“点击改按钮启动本人”时,界面没有产生任何扭转,然而却打印了如下日志:

图片

4、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 并没有从新创立,只是将它切换到栈顶而已。

正文完
 0