Activity的四种启动模式详解

Activity的启动模式有四种,具体就不说了,直接上代码实验

先来写个例子:

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.lyz.demo.start" >

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme" >
        <activity android:name=".MainActivity" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".OtherActivity"/>
    </application>

</manifest>

MainActivity.java

package com.lyz.demo.start;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private Button btn_one;
    private Button btn_two;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setTitle("我是01");
        Log.e("MainActivity", "新创建01----" + String.valueOf(getTaskId()));

        initView();
    }
    public void initView(){
        btn_one = (Button) findViewById(R.id.btn_one);
        btn_two = (Button) findViewById(R.id.btn_two);

        btn_one.setOnClickListener(this);
        btn_two.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_one:
                startActivity(new Intent(this,MainActivity.class));
                break;
            case R.id.btn_two:
                startActivity(new Intent(this,OtherActivity.class));
                break;
            default:
                break;
        }
    }
}

OtherActivity.java

package com.lyz.demo.start;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;

/**
 * Created by liyanzhen on 16/10/18.
 */
public class OtherActivity extends AppCompatActivity implements View.OnClickListener{
    private Button btn_one;
    private Button btn_two;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_other);
        setTitle("我是02");
        Log.e("OtherActivity","新创建02----" + String.valueOf(getTaskId()));

        initView();
    }

    public void initView(){
        btn_one = (Button) findViewById(R.id.btn_one);
        btn_two = (Button) findViewById(R.id.btn_two);

        btn_one.setOnClickListener(this);
        btn_two.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_one:
                startActivity(new Intent(this,MainActivity.class));
                break;
            case R.id.btn_two:
                startActivity(new Intent(this,OtherActivity.class));
                break;
            default:
                break;
        }
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/btn_one"
        android:text="我是页面一"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <Button
        android:id="@+id/btn_two"
        android:text="我是页面二"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

activity_other.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/btn_one"
        android:text="我是页面一"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <Button
        android:id="@+id/btn_two"
        android:text="我是页面二"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

Run

自动打开应用后,点击硬件返回,手动打开应用,再点击硬件返回,查看log信息:

com.lyz.demo.start E/MainActivity: 新创建01----5957
com.lyz.demo.start E/MainActivity: 新创建01----5958
com.lyz.demo.start E/MainActivity: 新创建01----5959
com.lyz.demo.start E/MainActivity: 新创建01----5960
com.lyz.demo.start E/MainActivity: 新创建01----5961
com.lyz.demo.start E/MainActivity: 新创建01----5962

结论:

任务栈:每打开一次应用程序,默认情况下,开启一个任务栈,来维护activity的组件,其中任务栈的Id是自增长的。

====================重点来了===================

脑子里边记着:
MainActivity   ----->  始终是standard(默认)模式
OtherActivity  ----->  随着讲解修改为对应模式

1、standard ( the default model )

上面的例子中,修改两个activity的声明
设置属性为android:launchMode=”standard”后

Run

点击按钮1,点击按钮2,点击按钮2,点击按钮2,点击按钮1,查看log:

com.lyz.demo.start E/MainActivity:  新创建01----6016
com.lyz.demo.start E/MainActivity:  新创建01----6016
com.lyz.demo.start E/OtherActivity: 新创建02----6016
com.lyz.demo.start E/OtherActivity: 新创建02----6016
com.lyz.demo.start E/OtherActivity: 新创建02----6016
com.lyz.demo.start E/MainActivity:  新创建01----6016

结论:

这里写图片描述

此时,当我们点击6次返回时,应用才会退出。

standard

特点:在当前任务栈中,当调用startActivity方法开启界面,会实例化多个实例对象在任务栈中,互相不影响。

问题:会在任务栈中实例化多个对象,重复的太多,容易内存溢出。

2、singleTop(单顶部模式)

上面的例子中,修改AndroidManifest.xml中OtherActivity的声明
设置属性为android:launchMode=”singleTop”

并在OtherActivity.java中增加以下方法:

@Override
    protected void onNewIntent(Intent intent) {
        Log.e("OtherActivity","onNewIntent方法被调用了!");
        super.onNewIntent(intent);
    }

Run

应用自动启动后,点击按钮2,点击按钮2,点击按钮2,点击按钮1,点击按钮1,点击按钮2,点击按钮2,查看log:

com.lyz.demo.start E/MainActivity:  新创建01----6018
com.lyz.demo.start E/OtherActivity: 新创建02----6018
com.lyz.demo.start E/OtherActivity: onNewIntent方法被调用了!
com.lyz.demo.start E/OtherActivity: onNewIntent方法被调用了!
com.lyz.demo.start E/MainActivity:  新创建01----6018
com.lyz.demo.start E/MainActivity:  新创建01----6018
com.lyz.demo.start E/OtherActivity: 新创建02----6018
com.lyz.demo.start E/OtherActivity: onNewIntent方法被调用了!

这里写图片描述

此时,当我们点击5次返回时,应用才会退出。

结论:

如果被开启的activity已经在任务栈的顶部,这时候不会创建一个新的实例,而是调用栈顶activity的onNewIntent方法。

如果当前任务栈中已经有被开启的activity,但是不在顶部,这时候会创建一个新的实例在任务栈中。

3、singleTask(单任务栈模式)

上面的例子中,修改AndroidManifest.xml中OtherActivity的声明
设置属性为android:launchMode=”singleTask”

Run

应用自动启动后,点击按钮2,点击按钮1,点击按钮1,点击按钮1,点击按钮2,点击按钮2,查看log:

com.lyz.demo.start E/MainActivity:  新创建01----6020
com.lyz.demo.start E/OtherActivity: 新创建02----6020
com.lyz.demo.start E/MainActivity:  新创建01----6020
com.lyz.demo.start E/MainActivity:  新创建01----6020
com.lyz.demo.start E/MainActivity:  新创建01----6020
com.lyz.demo.start E/OtherActivity: onNewIntent方法被调用了!
com.lyz.demo.start E/OtherActivity: onNewIntent方法被调用了!

这里写图片描述

此时,当我们只需点击2次返回,应用即可退出。

结论:

如果被开启的activity已经在任务栈中,则调用startActivity方法开启此页面时,不会再创建一个新的实例,而是把当前的activity显示出来,提到栈顶,同时,会把当前任务栈中activity以上的所有activity清除出栈。

如果当前的activity已经在栈顶,直接调用onNewIntent方法。

应用场景:一般用在页面加载非常庞大时,非常消耗资源,只想初始化一次。

4、singleInstance(单一实例)

上面的例子中,修改AndroidManifest.xml中OtherActivity的声明
设置属性为android:launchMode=”singleInstance”

Run

应用自动启动后,点击按钮2,点击按钮1,点击按钮1,点击按钮1,点击按钮2,点击按钮2,查看log:

com.lyz.demo.start E/MainActivity:  新创建01----6022
com.lyz.demo.start E/OtherActivity: 新创建02----6023
com.lyz.demo.start E/MainActivity:  新创建01----6022
com.lyz.demo.start E/MainActivity:  新创建01----6022
com.lyz.demo.start E/MainActivity:  新创建01----6022
com.lyz.demo.start E/OtherActivity: onNewIntent方法被调用了!
com.lyz.demo.start E/OtherActivity: onNewIntent方法被调用了!                                                                

这里写图片描述

此时,当我们点击5次返回时,应用退出。

结论:

如果被开启的activity没有实例化过对象时,调用startActivity开启页面时,会创建一个新的任务栈给activity使用,并且当前任务栈只有它自己存在,其他的activity不会在此任务栈中创建新的实例。

如果被开启的activity已经实例化过,那么会调用onNewIntent方法。

singleInstance附加说明:
(1)在上面那个应用中,在AndroidManifest.xml文件中找到OtherActivity的声明,修改为:

<activity
            android:name=".OtherActivity"
            android:launchMode="singleInstance">
            <intent-filter>
                <action android:name="com.lyz.demo.start.activity02"/>

                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>

(2)新增一个应用
MainActivity.java

package com.lyz.demo.singleInstance;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {
    private Button btn_app;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setTitle("我是新应用");
        Log.e("我是新应用", "----" + getTaskId());

        initView();
    }

    public void initView(){
        btn_app = (Button) findViewById(R.id.btn_app);
        btn_app.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.setAction("com.lyz.demo.start.activity02");
                intent.addCategory(Intent.CATEGORY_DEFAULT);//可加可不加,默认就是default
                startActivity(intent);
            }
        });
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/btn_app"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="跳转至02" />
</RelativeLayout>

Run

1)先Run应用一,自动启动后,点击按钮2,点击按钮1,点击按钮12)Run应用二,自动启动后,点击按钮,查看应用一的log:

com.lyz.demo.start E/MainActivity:   新创建01----6038
com.lyz.demo.start E/OtherActivity:  新创建02----6039
com.lyz.demo.start E/MainActivity:   新创建01----6038
com.lyz.demo.start E/MainActivity:   新创建01----6038
com.lyz.demo.start E/OtherActivity:  onNewIntent方法被调用了!

结论:

在整个系统中,无论哪一个应用程序开启当前采用singleInstance的activity,如果已经实例化过,那么始终都是调用的同一个activity,而且是在同一个任务栈中。

应用场景:需要常驻在系统中的页面采用singleInstance模式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值