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 並無從新建立,只是將它切換到棧頂而已。