android Activity launch mode 一个实例 singleInstance

参考:http://blog.csdn.net/zhangjg_blog/article/details/10923643#

singleInstance的特点可以归结为以下三条:

  1. 以singleInstance模式启动的Activity具有全局唯一性,即整个系统中只会存在一个这样的实例
  2. 以singleInstance模式启动的Activity具有独占性,即它会独自占用一个任务,被他开启的任何activity都会运行在其他任务中(官方文档上的描述为,singleInstance模式的Activity不允许其他Activity和它共存在一个任务中)
  3. 被singleInstance模式的Activity开启的其他activity,能够开启一个新任务,但不一定开启新的任务,也可能在已有的一个任务中开启
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.jg.zhang.androidtasktest"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="17" />

    <application android:allowBackup="true"
        android:icon="@drawable/ic_launcher" android:label="androidtasktest">

        <activity  android:name="com.jg.zhang.androidtasktest.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

         <activity android:name="com.jg.zhang.androidtasktest.SecondActivity"
             android:launchMode="singleInstance">
             <intent-filter>
                 <action android:name="com.jg.zhang.androidtasktest.ACTION_MY"/>
                 <category android:name="android.intent.category.DEFAULT"/>
             </intent-filter>
         </activity>

         <activity android:name="com.jg.zhang.androidtasktest.ThirdActivity"/>

    </application>

</manifest>

  

由上面的清单文件可以知道,该应用包括三个activity,分别为MianActivity,SecondActivity,ThirdActivity,其中SecondActivity启动模式设置为singleInstance。MianActivity可以开启SecondActivity,SecondActivity可以开启ThirdActivity。 并且为了可以在其他应用中开启SecondActivity,为SecondActivity设置了一个IntentFilter,这样就可以在其他应用中使用隐式Intent开启SecondActivity。

为了更好的验证singleInstance的全局唯一性,还需要其他一个应用,对上面的AndroidTaskTest1进行一些修改即可。AndroidTaskTest1只需要一个MianActivity,在MainActivity中点击按钮会开启AndroidTaskTest应用中的SecondActivity。开启AndroidTaskTest应用中的SecondActivity的代码如下

	/**
	 * 该方法在布局中按钮的android:onClick属性中指定
	 * android:onClick="launchOtherActivity"
	 * @param v
	 */
	public void launchOtherActivity(View v){
		Intent intent = new Intent();

		//以下Action为"com.jg.zhang.androidtasktest.ACTION_MY"
		//即AndroidTaskTest应用中SecondActivity的action
		intent.setAction("com.jg.zhang.androidtasktest.ACTION_MY");

		startActivity(intent);
	}

执行如下操作:安装AndroidTaskTest应用,点击MainActivity中的按钮,开启SecondActivity,可以看到如下log输出:  

执行adb shell dumpsys activity命令,有以下输出:
TaskRecord{411189e0 #9 A com.jg.zhang.androidtasktest}
Run #2: ActivityRecord{4129af80 com.jg.zhang.androidtasktest/.SecondActivity}
TaskRecord{41305528 #8 A com.jg.zhang.androidtasktest}
Run #1: ActivityRecord{41296e60 com.jg.zhang.androidtasktest/.MainActivity}
以上可以说明,singleInstance模式的Activity总是会在新的任务中运行(前提是系统中还不存在这样的一个实例) 。

下面验证它的全局唯一性,执行以下操作:安装另一个应用AndroidTaskTest1,在开启的MainActivity中点击按钮开启AndroidTaskTest应用中的SecondActivity。看到打印出一条新的日志:

执行adb shell dumpsys activity命令,有以下输出:

TaskRecord{411189e0 #9 A com.jg.zhang.androidtasktest}

Run #3: ActivityRecord{4129af80 com.jg.zhang.androidtasktest/.SecondActivity}

TaskRecord{412dc788 #12 A com.jg.zhang.androidtasktest1}

Run #2: ActivityRecord{4121c628 com.jg.zhang.androidtasktest1/.MainActivity}

TaskRecord{41305528 #8 A com.jg.zhang.androidtasktest}

Run #1: ActivityRecord{41296e60 com.jg.zhang.androidtasktest/.MainActivity}

由红色字体可以得知,开启的SecondActivity就是上次创建的编号为4129af80的SecondActivity,并且Log中没有再次输出关于SecondActivity的信息,说明SecondActivity并没有重新创建。由此可以得出结论:以singleInstance模式启动的Activity在整个系统中是单例的,如果在启动这样的Activity时,已经存在了一个实例,那么会把它所在的任务调度到前台,重用这个实例。

下面开始验证第二个特点:以singleInstance模式启动的Activity具有独占性,即它会独自占用一个任务,被他开启的任何activity都会运行在其他任务中

重新安装AndroidTaskTest应用,点击MainActivity中的按钮,开启SecondActivity,在SecondActivity中点击按钮,开启ThirdActivity。可以看到有如下Log输出:

。。。

SecondActivity所在的任务为16,被SecondActivity启动的ThirdActivity所在的任务为15,这就说明以singleInstance模式启动的Activity具有独占性,即它会独自占用一个任务,被他开启的任何activity都会运行在其他任务中

下面开始验证第三个特点:被singleInstance模式的Activity开启的其他activity,能够在新的任务中启动,但不一定开启新的任务,也可能在已有的一个任务中开启

有上面对第二个特点的验证可以看到,被SecondActivity启动的ThirdActivity并没有运行在一个新开启的任务中,而是和MainActivity运行在了同一个已有的任务中,那么在什么情况下ThirdActivity才会启动一个新的任务呢?

现在对程序的清单文件做以下修改,为ThirdActivity增加一个属性taskAffinity:

         <activity android:name="com.jg.zhang.androidtasktest.ThirdActivity"
             android:taskAffinity="com.jg.zhang.androidtasktest.second"/>

  

重新安装AndroidTaskTest应用,执行和上一步中同样的操作:点击MainActivity中的按钮,开启SecondActivity,在SecondActivity中点击按钮,开启ThirdActivity。可以看到有如下输出:

执行adb shell dumpsys activity命令,有以下输出:

TaskRecord{413551b0 #20 A com.jg.zhang.androidtasktest.second}
Run #3: ActivityRecord{412de9c0 com.jg.zhang.androidtasktest/.ThirdActivity}
TaskRecord{4134b268 #19 A com.jg.zhang.androidtasktest}
Run #2: ActivityRecord{412a36a0 com.jg.zhang.androidtasktest/.SecondActivity}
TaskRecord{413131e8 #18 A com.jg.zhang.androidtasktest}
Run #1: ActivityRecord{41271e10 com.jg.zhang.androidtasktest/.MainActivity}

可见,被SecondActivity启动的ThirdActivity启动在了一个新的任务中,即在启动ThirdActivity时创建了一个新任务。这就说明被singleInstance模式的Activity A在开启另一activity B时,能够开启一个新任务,但是是不是真的开启新任务,还要受其他条件的限制,这个条件是:当前系统中是不是已经有了一个activity B的taskAffinity属性指定的任务。

其实这种行为和singleTask启动时的情况相同。在Activity的启动模式设置为singleTask时,启动时系统会为它加上FLAG_ACTIVITY_NEW_TASK标志,而被singleInstance模式的Activity开启的activity,启动时系统也会为它加上FLAG_ACTIVITY_NEW_TASK标志,所以他们启动时的情况是相同的,上面再验证singleTask时已经阐述过,现在重新说明一下:

由于ThirdActivity是被启动模式为singleInstance类型的Activity(即SecondActivity)启动的,framework会为它它加上FLAG_ACTIVITY_NEW_TASK标志,这时  framework会检索是否已经存在了一个affinity为com.jg.zhang.androidtasktest.second(即ThirdActivity的taskAffinity属性)的任务,

  • 如果存在这样的一个任务,则检查在这个任务中是否已经有了一个ThirdActivity的实例,
  1. 如果已经存在一个ThirdActivity的实例,则会重用这个任务和任务中的ThirdActivity实例,将这个任务调到前台,清除位于ThirdActivity上面的所有Activity,显示ThirdActivity,并调用ThirdActivity的onNewIntent()。
  2. 如果不存在一个ThirdActivity的实例,会在这个任务中创建ThirdActivity的实例,并调用onCreate()方法
  • 如果不存在这样的一个任务,会创建一个新的affinity为com.jg.zhang.androidtasktest.second的任务,并且将ThirdActivity启动到这个新的任务中

如果ThirdActivity不设置taskAffinity,即ThirdActivity和MainActivity的taskAffinity相同,都为应用的包名,那么ThirdActivity是不会开启一个新任务的,framework中的判定过程如下:

  1. 在SecondActivity启动ThirdActivity时,因为SecondActivity是singleInstance的,所以设定ThirdActivity的启动标志为FLAG_ACTIVITY_NEW_TASK
  2. 然后获得ThirdActivity的taskAffinity,即为包名com.jg.zhang.androidtasktest
  3. 检查是否已经存在一个affinity为com.jg.zhang.androidtasktest的任务,这个任务是存在的,就是MainActivity所在的任务,这个任务是在启动MainActivity时开启的
  4. 既然已经存在这个任务,就检索在这个任务中是否存在一个ThirdActivity的实例,发现不存在
  5. 在这个已有的任务中启动一个SecondActivity的实例

为了作一个清楚的比较,列出ThirdActivity的taskAffinity属性设为com.jg.zhang.androidtasktest.second时的启动过程

  1. 在SecondActivity启动ThirdActivity时,因为SecondActivity是singleInstance的,那么设定ThirdActivity的启动标志为FLAG_ACTIVITY_NEW_TASK
  2. 然后获得ThirdActivity的taskAffinity,即为com.jg.zhang.androidtasktest.second
  3. 检查是否已经存在一个affinity为com.jg.zhang.androidtasktest.second的任务,这个任务是不存在的
  4. 创建一个新的affinity为com.jg.zhang.androidtasktest.second的任务,并且将ThirdActivity启动到这个新的任务

到此singleInstance也介绍完了。

时间: 2024-10-06 15:36:41

android Activity launch mode 一个实例 singleInstance的相关文章

android Activity launch mode 一个实例

参考:http://blog.csdn.net/ljz2009y/article/details/26621815 一个应用 三个页面 第二个页面设置为 singlTask <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.jg.

android Activity launch mode 知识点总结

阅读 http://my.oschina.net/u/1244156/blog/228483 FLAG_ACTIVITY_NEW_TASK 会启动被调用者TaskAffinity(如果不定义默认就是所在的Application的包名)决定的Task栈 (即 如果 只有A,B的应用,开启应用 A带newTask启动B还是在同一Task栈中) FLAG_ACTIVITY_CLEAR_TOP 清除Task栈中被调用者以上的Activity(包括调用者,即调用B的onDestroy,onCreate方法

Android -- Activity接收另一个Activity返回的数据

当我们在一个A(Activity)跳转到另外一个B(Activity)时,再由B返回A时,A如何接受返回的数据. 我们在B页面加了一个输入框和按钮,当输入数据,点击按钮返回信息到A页面,先来看B页面Activity代码 package com.example.testapp; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.Menu;

Android Activity启动模式的功能验证

之前一直都是看别人写的启动模式,发现网上大多数的内容都是抄袭来抄袭去,直到最近看了开发艺术这本书,发现之前对启动模式的理解过于简单,很多东西都没有考虑到,为了加深理解,于是决定自己动手去验证一下四个启动模式.当然我们也从最简单的启动模式开始验证. 为了打印方便,定义一个基础Activity,在其onCreate方法和onNewIntent方法中打印出当前Activity的日志信息,主要包括所属的task,当前类的hashcode,以及taskAffinity的值.之后我们进行测试的Activit

Android——Activity以及Service的启动方式

1. Activity共有四种启动方式(android:launchMode) (1) standard:默认方式,不用再次配置 standart模式就是一个栈的模式,默认每次跳转到一个新的Activity都会新建一个实例,不管这个实例是否存在.每次跳转就新建,压栈,每次返回就pop弹栈. (2) singleTop:为<activity>指定属性android:launchMode="singleTop",栈顶重复使用模式. 每次判断栈顶有没有,没有,创建:有,继续使用.

如何防止PendingIntent打开一个Activity的多个实例

正在写一个app,这个app会定时刷新Notification,点击Notification时会开启主Activity,令人烦恼的是,会打开主Activity的多个实例. 研究了好久PendingIntent的使用方法,研究了如何判断Activity是否已经存在于内存中,后来发现只要一句话即可解决此问题: <activity android:launchMode="singleInstance" > 就是这么简单.:P 版权声明:本文为博主原创文章,未经博主允许不得转载.

【React Native开发】React Native For Android环境配置以及第一个实例

转载请标明出处: http://blog.csdn.net/developer_jiangqq/article/details/50456967 本文出自:[江清清的博客] (一)前言 FaceBook早期开源发布了React Native For IOS,终于在2015年9月15日也发布了ReactNative for Android,虽然Android版本的项目发布比较迟,但是也没有阻挡了广大开发者的热情.可以这样讲在2015年移动平台市场上有两个方向技术研究比较火,第一种为阿里,百度,腾讯

【起航计划 007】2015 起航计划 Android APIDemo的魔鬼步伐 06 App-&gt;Activity-&gt;Forwarding Activity启动另外一个Activity finish()方法

Android应用可以包含多个Activity,某个Activity可以启动另外的Activity. 这些Activity采用栈结构来管理,新打开的Activity叠放在当前的Activity之上,当前的Activity停止运行. 当一个Activity停止运行时,Android系统保留其停止前的状态,当用户按下“Back”按键时,栈最上的Activity从栈顶退栈,之前的Activity移到栈顶,显示在屏幕上: 有些时候,当一个Activity启动新的Activity后,不希望把当前Activ

Android 判断当前Activity是不是最后一个Activity 以及 应用或Activity是否存在

判断当前Activity是最后一个Activity: 在Activity的方法中, 有一个方法isTaskRoot()方法, 这个方法可以判断当前Activity是否是最后一个Activity, 如果是, 用户再按一次返回键就退出应用, 否则回到上一个仍然活动的Activity; 代码如下: @Override public void onBackPressed() { if (isTaskRoot()) { Toast.makeText(mContext, "当前activity是该应用唯一