Activity的四种启动模式和应用场景

Activity的四种启动模式和应用场景

简介

通过设置ActivityManifestActivity_launchMode可以设置Activity的启动模式。

默认情况下,使用启动模式:standard

同时,launchMode可以通过Intent flags的改变在运行时被复写,比
如 Intent flags FLAG_ACTIVITY_SINGLE_TOPFLAG_ACTIVITY_NEW_TASK,
FLAG_ACTIVITY_MULTIPLE_TASK.

四种模式

Constant

Value

Description

standard

0

默认模式,会在启动时创建一个新实例,创建的模式也可以随Intent.FLAG_ACTIVITY_NEW_TASK而改变

singleTop

1

当启动activity时,有相同的activity在前台与用户交互,那就复用这个activity,这个实例会被调用Activity.onNewIntent()

singleTask

2

在启动activity时,若有一个运行着这个activitytask,那这个activity实例会被调到前台,并调用Activity.onNewIntent() ,启动实例的Intentflag会被设置Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT . singleTasksingleTop的一个扩展集。This is a superset of the singleTop mode, where if there is already an instance of the activity being started at the top of the stack, it will receive the Intent as described there (without the FLAG_ACTIVITY_BROUGHT_TO_FRONT flag set). See the Tasks and Back Stack document for more details about tasks.

singleInstance

3

开辟一个只允许一个activity实例在里头运行的task. 如果用同样的intent再次启动这个activitytask会被调到前台,其Activity.onNewIntent() 会被调用. 如果这个activity实例要启动一个新activity,那么这个新activity会在一个新task中运行.

Demo范例调试

目录结构:MainActivityActivity1\Activity2Activity3

唯一的一个layout

<RelativeLayout

    ......

    tools:context="com.example.testlaunchermode.MainActivity" >

 

    <TextView

        android:id="@+id/txt_this"

        ... />

    <Button

        android:id="@+id/btn_activity_1"

        ....

        android:text="btn_activity1" />

    <Button

        android:id="@+id/btn_activity_2"

        ...

        android:text="btn_activity2" />

    <Button

        android:id="@+id/btn_activity_3"

        ...

        android:text="btn_activity3" />

</RelativeLayout>

几个除了红色字体外,其余全部一模一样的Activity

public class Activity2 extends ActionBarActivity {

Button mBtnAct1, mBtnAct2, mBtnAct3;

TextView mTxtThis;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        mTxtThis = (TextView) findViewById(R.id.txt_this);

        mTxtThis.setText(Activity2.this.toString());

       android.util.Log.e("TestLauncherMode", Activity2.this + " onCreate");

        mBtnAct1 = (Button) findViewById(R.id.btn_activity_1);

        mBtnAct1.setOnClickListener(new View.OnClickListener() {

                @Override

                public void onClick(View v) {

                        android.util.Log.e("TestLauncherMode", Activity2.this + " navigate to Activity1");

                        startActivity(new Intent(getBaseContext(), Activity1.class));

                }

        });

        mBtnAct2 = (Button) findViewById(R.id.btn_activity_2);

        mBtnAct2.setOnClickListener(new View.OnClickListener() {

                @Override

                public void onClick(View v) {

                        android.util.Log.e("TestLauncherMode", Activity2.this + " navigate to Activity2");

                        startActivity(new Intent(getBaseContext(), Activity2.class));

                }

        });

        mBtnAct3 = (Button) findViewById(R.id.btn_activity_3);

        mBtnAct3.setOnClickListener(new View.OnClickListener() {

                @Override

                public void onClick(View v) {

                        android.util.Log.e("TestLauncherMode", Activity2.this + " navigate to Activity3");

                        startActivity(new Intent(getBaseContext(), Activity3.class));

                }

        });

    }

    public void onStop(){

     super.onStop();

     android.util.Log.e("TestLauncherMode", Activity2.this + " onStop");

    }

}

红色字体,相应替换就OK了。

AndroidManifest.xml

  ......

        <activity

            android:name=".MainActivity"

            android:label="@string/app_name" >

            <intent-filter>

                <action android:name="android.intent.action.MAIN" />

 

                <category android:name="android.intent.category.LAUNCHER" />

            </intent-filter>

        </activity>

        <activity android:name="Activity1" />

        <activity android:name="Activity2" />

        <activity android:name="Activity3" />

  ......

前提注释:从Launcher启动的Activity,肯定是NEW_TASK。这点可以查看Launcher的源码。

模式1:standard。默认模式。
操作如下:MainActivity->Activity1->Activity1->Activity1->Back->Back->Back->Back

 

仔细看一下這个log转换成图形

这是默认的启动模式,每次启动,都启动一个new Instance

模式2:singleTop

这个范例把Activity1launchMode=”singleTop”

操作如下:
MainActivity->Activity1->Activity1->Activity1->Activity1->Activity1->Activity2->Activity3->Activity1->Activity1->Back->Back->Back->Back

 

仔细看navigate的字段,这些是点击跳转时打印的动作信息。

转换成图形

 

可以看出,当task顶部有singleTopActivity时,就复用;若没有就重新创建。

singleTop:就是栈顶只有一个instance

适合  接受推送消息的展示页

某些本应只展示一个的场景,比如一下子收到一堆推送消息,不能每个都弹出来吧。但凡是这样的都行。优酷的推荐视频,电商app推送一个活动。

模式3:singleTask---Activity2设置成singleTask

 

转换成图形

 

为什么会这样呢。因为Activity2singleTask,如果task里没有就new,若有,就把Activity2之上的全部移除掉。这样,自己就变成了顶。所以说,singleTasksingleTop的扩展。

singleTop:顶上不是target Activitynew一个

singleTask:顶上不是target Activity,移除target之上的,把自己变成top

singleTask的特性是头上不允许有任何task。也不会有重复的instance。在target Activity之后的任何activity都会被干掉。等于重生啊。

适合程序入口,不需要启动后activity

是的,只能用在启动页了吧,首页,这种只允许有一个instance,如果有其他就移除掉它顶上的。从这个Activity进入的其他activity都抛弃掉了。用户要再操作一次。

官网的文档说----make sure to test the usability of the activity during launch

确实,得好好考虑下,不是所有activity都可以用的

模式4:singleInstance-activity2设置成singleInstance


转换成图形

 

这图有点复杂。两个框代表两个task,这应没什么问题。下框没连接部分,都跑到Activity2去了。

可以看到一启动到Activity2就会重新开辟一个task。而这里头的task只有一个activity2.

在返回的时候,是一个task,一个task的返回的。

要从当前的task开始,上图task2结束后就跳转到task1了。

singleInstance的特性是  完全同程序分离。完全独立运行的。

同样的也要想清楚再用。

适合需要与程序分离开的页面。

这种页面包括,闹钟的提示框。有兴趣的朋友可以看下package/app下的源码,grep一把,就会发现是这样的


框内是内部apk的独特应用。也用的singleInstance。就不混淆视听了。

 

小结

使用方式:

standard:怎么样都要创建

singleTop:顶上不是target Activitynew一个

singleTask:顶上不是target Activity,移除target之上的,把自己变成top

singleInstance:开辟私有的task,完全独立于程序的其他activitytask

使用场景:

standard:普通activity

singleTop:要展示推送过来的消息

singleTask:程序入口等启动页面

singleInstance:完全独立的,类似闹钟的提示


猜你喜欢

转载自blog.csdn.net/wangxueming/article/details/73294777