• Android Activity各启动模式的差异


    Activity共有四种启动模式:standard,singleTop,singleTask,singleInstance

    为了方便描述和理解,布局文件、Manifest文件和各个java文件如下:

    AndoirdManifest文件

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.activitylaunchmode"
        android:versionCode="1"
        android:versionName="1.0" >
    
        <uses-sdk
            android:minSdkVersion="19"
            android:targetSdkVersion="21" />
    
        <application
            android:allowBackup="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:theme="@style/AppTheme" >
            <activity
                android:launchMode="standard"
                android:screenOrientation="portrait"
                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:launchMode="singleTop"
                android:screenOrientation="portrait"
                android:name=".SecondActivity">
            </activity>
            <activity
                android:launchMode="singleTask"
                android:screenOrientation="portrait"
                android:name=".ThirdActivity">
            </activity>
            <activity 
                android:launchMode="singleInstance"
                android:screenOrientation="portrait"
                android:name=".FourActivity">
            </activity>
        </application>
    
    </manifest>
    View Code

      4个Activity分别对应一种启动模式:

        MainActivity     ---->  standard (默认模式,写不写都可以)

        SecondActivity ---->  singleTop

        ThirdActivty     ---->  singleTask

        FourActivity     ---->  singleInstance

    布局文件 activity_main.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="com.example.activitylaunchmode.MainActivity" >
        
        <TextView 
            android:id="@+id/mTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            />
        <Button
            android:layout_below="@id/mTextView"
            android:id="@+id/buttonOne"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button1"
            />    
        <Button 
            android:id="@+id/buttonTwo"
            android:text="Button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@id/buttonOne"
               android:layout_below="@id/mTextView"
            />
        <Button 
            android:id="@+id/buttonThree"
            android:text="Button3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/buttonOne"
            />
        <Button 
            android:id="@+id/buttonFour"
            android:text="Button4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/buttonTwo"
            android:layout_toRightOf="@id/buttonThree"
            />
    </RelativeLayout>
    View Code

    MainActivity.java

    package com.example.activitylaunchmode;
    
    import android.app.Activity;
    import android.content.Intent;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.TextView;
    
    public class MainActivity extends Activity implements OnClickListener{
    
        private static final String TAG = "MainActivity";
        TextView tv;
        Button ButtonOne;
        Button ButtonTwo;
        Button ButtonThree;
        Button ButtonFour;
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            tv = (TextView) findViewById(R.id.mTextView);
            tv.setText("MainActivity");
            ButtonOne = (Button) findViewById(R.id.buttonOne);
            ButtonOne.setOnClickListener(this);
            ButtonTwo = (Button) findViewById(R.id.buttonTwo);
            ButtonTwo.setOnClickListener(this);
            ButtonThree = (Button) findViewById(R.id.buttonThree);
            ButtonThree.setOnClickListener(this);
            ButtonFour = (Button) findViewById(R.id.buttonFour);
            ButtonFour.setOnClickListener(this);
        }
        
        @Override
        protected void onNewIntent(Intent intent) {
            // TODO Auto-generated method stub
            super.onNewIntent(intent);
            Log.d(TAG, "onNewIntent");
        }
    
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            switch (v.getId()) {
            case R.id.buttonOne:
                Intent mainIntent = new Intent(this,MainActivity.class);
                startActivity(mainIntent);
                break;
            case R.id.buttonTwo:
                Intent secondIntent = new Intent(this,SecondActivity.class);
                startActivity(secondIntent);
                break;
            case R.id.buttonThree:
                Intent ThirdIntent = new Intent(this,ThirdActivity.class);
                startActivity(ThirdIntent);
                break;
            case R.id.buttonFour:
                Intent FourIntent = new Intent(this,FourActivity.class);
                startActivity(FourIntent);
                break;
            }
        }
    }
    View Code

    SecondActivity.java

    package com.example.activitylaunchmode;
    
    import android.app.Activity;
    import android.content.Intent;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.TextView;
    
    public class SecondActivity extends Activity implements OnClickListener {
        
        private static final String TAG = "SecondActivity";
        TextView tv;
        Button ButtonOne;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            // TODO Auto-generated method stub
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            tv = (TextView) findViewById(R.id.mTextView);
            tv.setText("SecondActivity");
            ButtonOne = (Button) findViewById(R.id.buttonOne);
            ButtonOne.setOnClickListener(this);
        }
    
        @Override
        protected void onNewIntent(Intent intent) {
            // TODO Auto-generated method stub
            super.onNewIntent(intent);
            Log.d(TAG, "onNewIntent");
        }
    
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            switch (v.getId()) {
            case R.id.buttonOne:
                Intent secondIntent = new Intent(this,SecondActivity.class);
                startActivity(secondIntent);
                break;
            }
        }
    }
    View Code

    ThirdActivity.java

    package com.example.activitylaunchmode;
    
    import android.app.Activity;
    import android.content.Intent;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.TextView;
    
    public class ThirdActivity extends Activity implements OnClickListener {
    
        private static final String TAG = "ThirdActivity";
        TextView tv;
        Button ButtonOne;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            // TODO Auto-generated method stub
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            tv = (TextView) findViewById(R.id.mTextView);
            tv.setText("ThirdActivity");
            ButtonOne = (Button) findViewById(R.id.buttonOne);
            ButtonOne.setOnClickListener(this);
        }
        
        @Override
        protected void onNewIntent(Intent intent) {
            // TODO Auto-generated method stub
            super.onNewIntent(intent);
            Log.d(TAG, "onNewIntent");
        }
    
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            switch (v.getId()) {
            case R.id.buttonOne:
                Intent mainIntent = new Intent(this,MainActivity.class);
                startActivity(mainIntent);
                break;
    
            default:
                break;
            }
        }
        
    }
    View Code

    FourActivity.java

    package com.example.activitylaunchmode;
    
    import android.app.Activity;
    import android.content.Intent;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.TextView;
    
    public class FourActivity extends Activity implements OnClickListener {
    
        private static final String TAG = "FourActivity";
        TextView tv;
        Button ButtonOne;
        Button ButtonTwo;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            // TODO Auto-generated method stub
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            tv = (TextView) findViewById(R.id.mTextView);
            tv.setText("FourActivity");
            ButtonOne = (Button) findViewById(R.id.buttonOne);
            ButtonOne.setOnClickListener(this);
        }
        
        @Override
        protected void onNewIntent(Intent intent) {
            // TODO Auto-generated method stub
            super.onNewIntent(intent);
            Log.d(TAG, "onNewIntent");
        }
    
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            switch (v.getId()) {
            case R.id.buttonOne:
                Intent MainIntent = new Intent(this,MainActivity.class);
                startActivity(MainIntent);
                break;
    
            case R.id.buttonFour:
                Intent FourIntent = new Intent(this,FourActivity.class);
                startActivity(FourIntent);
            default:
                break;
            }
        }
        
    }
    View Code

     各个启动模式差异探究:

      1)standard:  默认模式,每启动一个activity都会在Task中创建一个,back键会依次从栈中退出

        MainActivity的启动模式是standard, 点击Button1,会再启动一个MainActivity.

        通过adb shell dumpsys activity命令, 我们能看到在Task中存在两个MainActivity.

        Task id #48
          TaskRecord{2cfa2efd #48 A=com.example.activitylaunchmode U=0 sz=2}
          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x30200000 cmp=com.example.activitylaunchmode/.MainActivity }
            Hist #1: ActivityRecord{37783c3a u0 com.example.activitylaunchmode/.MainActivity t48}
              Intent { cmp=com.example.activitylaunchmode/.MainActivity }
              ProcessRecord{358547f2 29163:com.example.activitylaunchmode/u0a134}
            Hist #0: ActivityRecord{363c8000 u0 com.example.activitylaunchmode/.MainActivity t48}
              Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x30200000 cmp=com.example.activitylaunchmode/.MainActivity bnds=[801,812][1047,1060] }
              ProcessRecord{358547f2 29163:com.example.activitylaunchmode/u0a134}
    
        Running activities (most recent first):
          TaskRecord{2cfa2efd #48 A=com.example.activitylaunchmode U=0 sz=2}
            Run #1: ActivityRecord{37783c3a u0 com.example.activitylaunchmode/.MainActivity t48}
            Run #0: ActivityRecord{363c8000 u0 com.example.activitylaunchmode/.MainActivity t48}

      

      2)singleTop:如果要启动的Activity在栈顶,则不会重新创建

         SecondActivity的启动模式是singleTop, 点击MainActivity中的Button2,会创建一个SecondActivity,再点击SecondActivity中的Button1,会重新启动 SecondActivity.

        通过adb命令,我们可以看到,Task中只有MainActivity和SecondActivity两个Activity,第二次点击并没有重新创建。从log中,我们可以看到,第二次点击启动SecondActivity,只是调用了前一个SecondActivity的onNewIntent方法。

        Task id #51
          TaskRecord{fb41e01 #51 A=com.example.activitylaunchmode U=0 sz=2}
          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x30200000 cmp=com.example.activitylaunchmode/.MainActivity }
            Hist #1: ActivityRecord{1ea62f6c u0 com.example.activitylaunchmode/.SecondActivity t51}
              Intent { cmp=com.example.activitylaunchmode/.SecondActivity }
              ProcessRecord{69b44a6 30061:com.example.activitylaunchmode/u0a134}
            Hist #0: ActivityRecord{27f7bb0a u0 com.example.activitylaunchmode/.MainActivity t51}
              Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x30200000 cmp=com.example.activitylaunchmode/.MainActivity bnds=[801,812][1047,1060] }
              ProcessRecord{69b44a6 30061:com.example.activitylaunchmode/u0a134}
    
        Running activities (most recent first):
          TaskRecord{fb41e01 #51 A=com.example.activitylaunchmode U=0 sz=2}
            Run #1: ActivityRecord{1ea62f6c u0 com.example.activitylaunchmode/.SecondActivity t51}
            Run #0: ActivityRecord{27f7bb0a u0 com.example.activitylaunchmode/.MainActivity t51}

      

      3)singleTask: 任务栈中没有这个Activity,则会在任务栈中创建一个实例,如果任务栈中已经存在,则会将任务栈中的此activity之上的activity全部出栈

        ThirdActivity的启动模式是singleTask, 点击MainActivity中的Button3,启动ThirdActivity,再点击ThirdActivity中的Button1,启动MainActivity,此时的Activity的堆栈信息如下:

        Task id #52
          TaskRecord{147eed75 #52 A=com.example.activitylaunchmode U=0 sz=3}
          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x30200000 cmp=com.example.activitylaunchmode/.MainActivity }
            Hist #2: ActivityRecord{2bf26a69 u0 com.example.activitylaunchmode/.MainActivity t52}
              Intent { cmp=com.example.activitylaunchmode/.MainActivity }
              ProcessRecord{3e2f10a 30540:com.example.activitylaunchmode/u0a134}
            Hist #1: ActivityRecord{147e2631 u0 com.example.activitylaunchmode/.ThirdActivity t52}
              Intent { flg=0x10000000 cmp=com.example.activitylaunchmode/.ThirdActivity }
              ProcessRecord{3e2f10a 30540:com.example.activitylaunchmode/u0a134}
            Hist #0: ActivityRecord{4e87389 u0 com.example.activitylaunchmode/.MainActivity t52}
              Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x30200000 cmp=com.example.activitylaunchmode/.MainActivity bnds=[801,812][1047,1060] }
              ProcessRecord{3e2f10a 30540:com.example.activitylaunchmode/u0a134}
    
        Running activities (most recent first):
          TaskRecord{147eed75 #52 A=com.example.activitylaunchmode U=0 sz=3}
            Run #2: ActivityRecord{2bf26a69 u0 com.example.activitylaunchmode/.MainActivity t52}
            Run #1: ActivityRecord{147e2631 u0 com.example.activitylaunchmode/.ThirdActivity t52}
            Run #0: ActivityRecord{4e87389 u0 com.example.activitylaunchmode/.MainActivity t52}

        这个也说明了standard启动模式会重新创建一个Activity.

        然后再点击MainActivity中的Button3,启动ThirdActivity,通过adb命令看到的如下: 

        Task id #53
          TaskRecord{2553d3b2 #53 A=com.example.activitylaunchmode U=0 sz=2}
          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x30200000 cmp=com.example.activitylaunchmode/.MainActivity }
            Hist #1: ActivityRecord{33f3f7cd u0 com.example.activitylaunchmode/.ThirdActivity t53}
              Intent { flg=0x10000000 cmp=com.example.activitylaunchmode/.ThirdActivity }
              ProcessRecord{1cdd8f03 30924:com.example.activitylaunchmode/u0a134}
            Hist #0: ActivityRecord{e5f9ea5 u0 com.example.activitylaunchmode/.MainActivity t53}
              Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x30200000 cmp=com.example.activitylaunchmode/.MainActivity bnds=[801,812][1047,1060] }
              ProcessRecord{1cdd8f03 30924:com.example.activitylaunchmode/u0a134}
    
        Running activities (most recent first):
          TaskRecord{2553d3b2 #53 A=com.example.activitylaunchmode U=0 sz=2}
            Run #1: ActivityRecord{33f3f7cd u0 com.example.activitylaunchmode/.ThirdActivity t53}
            Run #0: ActivityRecord{e5f9ea5 u0 com.example.activitylaunchmode/.MainActivity t53}

          能看到Task中现在只有两个Activity,ThirdActivity并没有重新创建,靠后的一个MainActivity也被弹出栈,从log也能看出调用了onNewIntent方法,

      

      4)singleInstance: 只有一个实例,运行于独立的task,启动此Activity的时候如果已经创建,则不会重新创建

        FourActivity的启动模式是singleInstance,点击MainActivity中的Button4,会启动FourActivity

        通过adb shell dumpsys activity命令,我们能看到两个Activity在不同的Task中,    

        Task id #55
          TaskRecord{11be8b0d #55 A=com.example.activitylaunchmode U=0 sz=1}
          Intent { flg=0x10000000 cmp=com.example.activitylaunchmode/.FourActivity }
            Hist #0: ActivityRecord{1cd2b9e5 u0 com.example.activitylaunchmode/.FourActivity t55}
              Intent { flg=0x10000000 cmp=com.example.activitylaunchmode/.FourActivity }
              ProcessRecord{358d5ac2 31514:com.example.activitylaunchmode/u0a134}
        Task id #54
          TaskRecord{12e2f0d3 #54 A=com.example.activitylaunchmode U=0 sz=1}
          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x30200000 cmp=com.example.activitylaunchmode/.MainActivity }
            Hist #0: ActivityRecord{374dcd03 u0 com.example.activitylaunchmode/.MainActivity t54}
              Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x30200000 cmp=com.example.activitylaunchmode/.MainActivity bnds=[801,812][1047,1060] }
              ProcessRecord{358d5ac2 31514:com.example.activitylaunchmode/u0a134}
    
        Running activities (most recent first):
          TaskRecord{11be8b0d #55 A=com.example.activitylaunchmode U=0 sz=1}
            Run #1: ActivityRecord{1cd2b9e5 u0 com.example.activitylaunchmode/.FourActivity t55}
          TaskRecord{12e2f0d3 #54 A=com.example.activitylaunchmode U=0 sz=1}
            Run #0: ActivityRecord{374dcd03 u0 com.example.activitylaunchmode/.MainActivity t54}

         如果再点击FourActivity中的Button4,也不会重新创建,从log可以看出,会调用onNewIntent方法,这里就不在贴activity的信息。

         adb shell dumpsys activity activities  也可以看到Task中各个activity的 launchMode.

        

  • 相关阅读:
    爬虫 效率
    Scrapy 数据存储 图片和文件
    装饰器
    Django 项目部署测试
    Django 项目部署
    Django JS
    三十九、管理信息系统 第三部分 作业
    三十八、模型分离(选做)
    三十七、密码保护
    三十六、实现搜索功能
  • 原文地址:https://www.cnblogs.com/xiaojianli/p/5646246.html
Copyright © 2020-2023  润新知