activity启动模式探究

activity有四种启动模式,熟悉启动模式可以帮我们更好使用activity。

模式设置两种方式:
first method,例如标准模式,Manifest 中:
activity中 android:launchMode=”standard”
second method,例如单例模式,activity中:
Intent i = new Intent(A.this,B.class);
i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(i);

standard 标准模式:
系统默认模式,这种模式下,每次启动activity都会创建一个实例,
这种方式下,谁启动这个activity,这个activity就运行在启动它的activity所在的任务栈中。
比如,activity A 启动了activity B,那么standard模式下,B会在A所在栈的上面.

singleTop 栈顶复用模式:
这种模式下,如果新的activity位于栈顶,那么activity不会创建新的实例,它的onNewIntent方法会被回调,可以获取当前请求的信息,同时注意它的onCreate()、onStart()不会被调用;如果新的activity没有位于栈顶,activity会被重新创建。

singleTask 栈内复用模式:
这是单实例模式,只要activity存在栈中,那么多次启动activity不会重新创建,与singleTop情况一样,并且也会执行
onNewIntent方法。我的理解就是当前被调用的activity如果没有任务栈就会创建任务栈,把activity实例入栈;如果存在任务栈,栈内有实例的话,就把它置顶并且调用onNewIntent,与此同时,如果被调用的activity栈内实例上方有其他实例,则会移除其他实例;如果存在任务栈,但是没有实例的话,就会创建实例,并且压入栈内。

singleInstance 单实例模式,可以理解为singleTask的加强版,与singleTask都是单实例模式,但是区别是singleInstance是一个任务栈内只有一个实例。

举例说明:
新建3个activity,并设置launchMode(启动模式),进行压栈操作。

MainActivity:
MainActivity.java代码

package com.lcl.view;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

public class MainActivity extends Activity {

    Context context;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.i("MM", "Main onCreate");
        // Activity正在被创建;可以做初始化操作 。比如调用setContentView加载界面布局资源,
        // 初始化Activity所需数据

    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Log.i("MM", "Main onRestart");
        //Activity重新启动,Activity从不可见到可见,onRestart会被调用
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.i("MM", "Main onStart");
        //Activity正在被启动;此时,Activity可见,但是还没有出现在前台,无法和用户交互,可理解为用户不可见
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.i("MM", "Main onResume");
        //Activity已经可见,并且出现在前台并开始活动;与onStart()方法都表示Activity已经可见,
        // 区别是onStart()是后台可见,onResume()是前台可见
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.i("MM", "Main onPause");
        //表示Activity正在停止,正常情况下,紧接着onStop会被执行
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.i("MM", "Main onStop");
        //Activity即将停止,可以做一些回收但不太耗时操作
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.i("MM", "Main onDestroy");
        //表示Activity即将被销毁,此时可以做一些回收和资源释放操作
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        String str = intent.getStringExtra("N");
        Log.i("MM", "str:"+str);

    }

    public void onClick(View view){
        Intent i = new Intent(MainActivity.this,Sec.class);
        i.putExtra("save","dd");
        startActivity(i);
    }
}

activity_main.xml代码:


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    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="com.lcl.view.MainActivity">

    <TextView
        android:background="#ff00ff"
        android:padding="15dp"
        android:textColor="#fff000"
        android:layout_marginTop="30dp"
        android:layout_marginLeft="20dp"
        android:onClick="onClick"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Main->Sec!" />
RelativeLayout>

Sec.java代码:

package com.lcl.view;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;

/**
 * Created by liuchunliang on 2017/2/21.
 */

public class Sec extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.sec);
        Log.i("MM", "Sec onCreate");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Log.i("MM", "Sec onRestart");
        //Activity重新启动,Activity从不可见到可见,onRestart会被调用
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.i("MM", "Sec onStart");
        //Activity正在被启动;此时,Activity可见,但是还没有出现在前台,无法和用户交互,可理解为用户不可见
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.i("MM", "Sec onResume");
        //Activity已经可见,并且出现在前台并开始活动;与onStart()方法都表示Activity已经可见,
        // 区别是onStart()是后台可见,onResume()是前台可见
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.i("MM", "Sec onPause");
        //表示Activity正在停止,正常情况下,紧接着onStop会被执行
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.i("MM", "Sec onStop");
        //Activity即将停止,可以做一些回收但不太耗时操作
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.i("MM", "Sec onDestroy");
        //表示Activity即将被销毁,此时可以做一些回收和资源释放操作
    }

    public void onClick(View view){
        Intent i = new Intent(Sec.this,Third.class);
        startActivity(i);
    }

}

sec.xml


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:background="#ff00ff"
        android:padding="15dp"
        android:textColor="#fff000"
        android:layout_marginTop="30dp"
        android:layout_marginLeft="20dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="onClick"
        android:text="Sec->Third!" />


LinearLayout>

Third.java

package com.lcl.view;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

/**
 * Created by liuchunliang on 2017/2/21.
 */

public class Third extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.third);
        Log.i("MM", "Third onCreate");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Log.i("MM", "Third onRestart");
        //Activity重新启动,Activity从不可见到可见,onRestart会被调用
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.i("MM", "Third onStart");
        //Activity正在被启动;此时,Activity可见,但是还没有出现在前台,无法和用户交互,可理解为用户不可见
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.i("MM", "Third onResume");
        //Activity已经可见,并且出现在前台并开始活动;与onStart()方法都表示Activity已经可见,
        // 区别是onStart()是后台可见,onResume()是前台可见
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.i("MM", "Third onPause");
        //表示Activity正在停止,正常情况下,紧接着onStop会被执行
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.i("MM", "Third onStop");
        //Activity即将停止,可以做一些回收但不太耗时操作
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.i("MM", "Third onDestroy");
        //表示Activity即将被销毁,此时可以做一些回收和资源释放操作
    }
    public void onClick(View view){
        Intent i = new Intent(Third.this,MainActivity.class);
        i.putExtra("N","ddd");
        startActivity(i);
    }
}

third.xml


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:background="#ff00ff"
        android:padding="15dp"
        android:textColor="#fff000"
        android:layout_marginTop="30dp"
        android:layout_marginLeft="20dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="onClick"
        android:text="Third->Main" />

LinearLayout>

AndroidManifest.xml:


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.lcl.view">

    <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"
            android:configChanges="orientation|screenSize"
            android:launchMode="standard">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            intent-filter>
        activity>
        <activity
            android:name=".Sec"
            android:configChanges="orientation|screenSize"
            android:launchMode="standard" />
        <activity
            android:name=".Third"
            android:configChanges="orientation|screenSize"
            android:launchMode="standard" />
    application>

manifest>

standard标准模式下,运行程序后生命周期:
01
Main进栈
此时,若是黑屏按电源键,后生命周期:
activity启动模式探究_第1张图片
黑屏时程序此时会执行onPause 然后onStop到后台用户不可见(黑屏怎么可能看见原来的activity呢),再次按下电源键点亮后onRestart重启 启动 用户可见的过程。

按下Main->Sec 跳转按钮后:
activity启动模式探究_第2张图片
跟预想的一样,先执行onPause 然后Sec 创建 启动 可见 最后MainActivity 执行onStop 用户不可见
Sec进栈
按下Sec->Third跳转按钮:
activity启动模式探究_第3张图片
Third进栈
按下Third->Main跳转按钮:
activity启动模式探究_第4张图片
虽然MainActivity之间创建过,但是在标准模式下,还是执行onCreate又创建了一遍,每次启动activity都会创建一个实例,
这种方式下,谁启动这个activity,这个activity就运行在启动它的activity所在的任务栈中。
此时任务栈为:
activity启动模式探究_第5张图片

再说说singleTop 栈顶复用模式吧,
此时修改manifest文件,修改MainActivity的launchMode为singleTop:

android:launchMode="singleTop"

并且修改MainActivity 跳转:

@Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        String str = intent.getStringExtra("save");
        Log.i("MM", "str:"+str);

    }
public void onClick(View view){
        Intent i = new Intent(MainActivity.this,MainActivity.class);
        i.putExtra("save","kkk");
        startActivity(i);
    }

activity_main.xml:
TextView文字修改为:

android:text="Main->Main!"

修改完后重新运行程序:

执行了onNewIntent,先执行onPause然后onNewIntent最后用户可见。可以看得出来没有重新创建新的activity;如果activity没有在栈顶,那么它会创建一个新的实例,并压栈。
singleTask 栈内复用模式下,修改原来的文件:
manifest.xml中
MainActivity中

android:launchMode="singleTask"

MainActivity.java中

 @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        String str = intent.getStringExtra("Save");
        Log.i("MM", "str:"+str);

    }

    public void onClick(View view){
        Intent i = new Intent(MainActivity.this,Sec.class);
        i.putExtra("save","kkk");
        startActivity(i);
    }

activity_main.xml:
TextView文字修改为:

android:text="Main->Sec!"

此时,从Main点击跳转到Sec,再从Sec到Third,此时点击“Third->Main”按钮,显示周期:
activity启动模式探究_第6张图片
Main->Sec->Third 栈内情况:
activity启动模式探究_第7张图片
当我们执行“Third->Main”按钮点击操作栈内情况:
09
为什么会只剩下一个了呢?singleTask这种模式下,如果它上方有实力,则会移除实例,同时也会执行onNewIntent。
singleInstance单实例模式:这种方式下一个任务栈内只有一个实例,
把所有activity的launchMode 修改为singleInstance

android:launchMode="singleInstance"

再重新运行程序:
Main->Sec->Third任务栈情况:
activity启动模式探究_第8张图片
可以看到建立3个任务栈,每个栈内有且只有一个实例,
当我们点击“Third->Main”按钮时:
activity启动模式探究_第9张图片
同样的singleInstance也会执行onNewIntent方法,因为是独立栈所以会执行重启操作,不会创建新的实例。

你可能感兴趣的:(Android)