Android Studio学习

活动的生命周期与启动

实验内容

  1. 首先建立一个新项目,在项目中添加一个新的Activity,这样就有了两个Activity;
    在这里插入图片描述

  2. 修改两个Activity的布局,为他们添加按钮用于跳转;为活动1添加按钮button_1,添加按钮text:"Goto Activity2"以及TextView:“this is activity1”;为活动2添加按钮button_2,添加text按钮:"Goto Activity1"以及TextView:“this is activity2”;
    在这里插入图片描述
    在这里插入图片描述

  3. 下一步就是在对应的activity中添加按钮点击的事件;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button=(Button) findViewById(R.id.button_1);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent=new Intent(MainActivity.this,Main2Activity.class); //活动1向活动2的跳转;
                startActivity(intent);
            }
        });
    }
    

    在这里插入图片描述

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        Button button=(Button) findViewById(R.id.button_2);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent=new Intent(Main2Activity.this,MainActivity.class); //活动2向活动1的跳转;
                startActivity(intent);
            }
        });
    }
    

    在这里插入图片描述

  4. 之后在活动1中添加代码来记录onCreate, onStart, onResume, on Pause, onStop,onDestroy以及onRestart函数的调用情况。

    package com.example.test3;
    
    import androidx.appcompat.app.AppCompatActivity;
    import android.content.Intent;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    
    public class MainActivity extends AppCompatActivity {
        public static final String TAG="main";
        @Override
        protected void onDestroy() {
            super.onDestroy();
            Log.d(TAG,"onDestory");
        }
    
        protected void onPause(){
            super.onPause();
            Log.d(TAG,"onPause");
        }
    
        protected void onResume(){
            super.onResume();
            Log.d(TAG,"onResume");
        }
    
        protected void onStop(){
            super.onStop();
            Log.d(TAG,"onStop");
        }
    
        protected void onRestart(){
            super.onRestart();
            Log.d(TAG,"onRestart");
        }
    
        protected void onStart(){
            super.onStart();
            Log.d(TAG,"onStart");
        }
    
        public String tmpData="I am original";
    
        @Override
        protected void onSaveInstanceState(Bundle outState) {
            super.onSaveInstanceState(outState);
            outState.putString("IS",tmpData);
        }
    
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Log.d(TAG,"onCreat");
            setContentView(R.layout.activity_main);
            if(savedInstanceState!=null)
            {
                tmpData=savedInstanceState.getString("IS");
                Log.d(TAG,tmpData);
            }
            Button button=(Button) findViewById(R.id.button_normal);
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    tmpData="I am changed";
                    Log.d(TAG,tmpData);
                    Intent intent=new Intent(MainActivity.this,normal.class);
                    startActivity(intent);
                }
            });
            Button button1=(Button) findViewById(R.id.button_dialog);
            button1.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Log.d(TAG,tmpData);
                    Intent intent=new Intent(MainActivity.this,dialog.class);
                    startActivity(intent);
                }
            });
        }
    }
    

    在这里插入图片描述

  5. 做好这些后,还需要在logcat界面添加过滤器来使得我们对onCreate, onStart, onResume, on Pause, onStop,onDestroy以及onRestart函数的调用情况有一个更直观的了解,否则log记录太过杂乱,很难得到我们需要的log信息;
    在这里插入图片描述
    在这里插入图片描述

  6. 接下来就是运行调试APP,打开APP,单击按钮实现活动1跳转到活动2;之后再按返回,依次关闭活动2,活动1;
    在这里插入图片描述
    在这里插入图片描述

  7. 跳转之后我们来看一下所作的Log记录;可以看出,APP运行的一开始需要执行onCreat,onStart,onResume来使得活动1开始运行;在我们点击了按钮跳转到活动2时,调用了函数onPause和onStop来暂停停止函数;之后当我们返回,由活动2返回至活动1时,调用了onRestart,onStart,onResume来使得活动1恢复运行,在最后关闭活动1时,则是调用了onPause,onStop,onDestory来结束这个活动;从这里我们看出,当活动出现跳转时会暂停原先的活动,并不会调用onDestory来结束这个活动,返回时则会使用onRestart,onStart,onResume来唤醒它,onPause,onStop往往组合使用,onStart,onResume也往往组合使用;
    在这里插入图片描述

  8. 接下来我并不是通过返回来回到活动1,而是通过活动2的按钮来跳转到活动1,之后再按返回依次关闭活动,来看一下log有什么不同;前半段与之前相同,直到onStop之后出现了onCreat,这与之前的onRestart不同,说明出现了一个新的活动1,之后按返回它一样onPause,onStop,onDestory结束了这个活动,后面就和之前相同返回结束了活动;这说明了活动2的跳转并不是回到原来的活动1,而是创建了一个新的活动1,这与我们之后探讨的活动启动模式相关联;
    在这里插入图片描述

  9. 接下来就是通过实验来证明系统可能会自行对活动运行onDestroy;首先打开APP,之后将它横屏变竖屏,观察log记录;
    在这里插入图片描述
    在这里插入图片描述

  10. 通过Logcat我们可以看到,在屏幕方向变化的这个过程,系统调用了onPause,onStop,onDestory,之后又重新onCreat创建了,这里就可以说明系统可能自行对活动运行onDestroy;
    在这里插入图片描述

  11. 接下来我们就是通过实验了解利用saveinstantstate处理系统自行运行onDestroy而导致数据丢失的情况;首先我为活动1添加了一个新的按钮,用来提示Log信息,来用于对比;并取消了button_1的跳转功能,改为修改数据信息并记录;
    在这里插入图片描述

  12. 之后对活动1的代码进行了修改,从而来调用saveinstantstate,以及对数据内容的记录;

    package com.example.test;
    
    import androidx.appcompat.app.AppCompatActivity;
    import android.content.Intent;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    
    public class MainActivity extends AppCompatActivity {
        public String TAG="main";
        protected void onDestroy() {
            super.onDestroy();
            Log.d(TAG,"onDestory");
        }
    
        @Override
        protected void onStart() {
            super.onStart();
            Log.d(TAG,"onStart");
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            Log.d(TAG,"onResume");
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            Log.d(TAG,"onPause");
        }
    
        protected void onStop(){
            super.onStop();
            Log.d(TAG,"onStop");
        }
    
        protected void onRestart(){
            super.onRestart();
            Log.d(TAG,"onRestart");
        }
        public String tmpData="I am original";     //原始数据
    
        @Override
        protected void onSaveInstanceState(Bundle outState) {      //非用户调用onDestory时调用,保存数据
            super.onSaveInstanceState(outState);
            outState.putString("IS",tmpData);
        }
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Log.d(TAG,"onCreat");
            setContentView(R.layout.activity_main);
            if(savedInstanceState!=null)                             //如果存有之前保存的信息,就读取
            {
                tmpData=savedInstanceState.getString("IS");
                Log.d(TAG,tmpData);
            }
            Button button=(Button) findViewById(R.id.button_1);
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    tmpData="I am changed";     //点击按钮会改变tmpData的内容
                    Log.d(TAG,tmpData);
                }
            });
            Button button1=(Button) findViewById(R.id.button_3);
            button1.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Log.d(TAG,tmpData);       //弹出当前tmpData的内容
                }
            });
        }
    }
    
    
  13. 打开APP,首先点击ORIGINAL,之后再点击CHANGE TMPDATA,再点击ORIGINAL;接下来再翻转屏幕点击ORIGINAL,查看logcat内容;
    在这里插入图片描述在这里插入图片描述

  14. 通过logcat我们可以看出,一开始tmpData的内容时**“I am original”,之后点击了CHANGE TMPDATA,内容变为了"I am changed";而ORIGINAL按钮的功能是记录当前tmpData的值,所以再次点击还是"I am changed";之后我们翻转屏幕,可以看到onDestory的执行,再点击ORIGINAL,记录的仍是"I am changed",之所以会有两个"I am changed"**是因为从savedInstanceState读取内容时也记录了依次tmpData;
    在这里插入图片描述

  15. 接下来我们将savedInstanceState相关读取和保存的代码注释掉,再来执行之前的操作,通过logcat的内容来进行对比;
    在这里插入图片描述

  16. 从这段log我们就可以看出前面半段的内容是相同的,重点是翻转之后的内容,即执行了onDestory之后的内容,执行了之后我们再次点击ORIGINAL,可以看到logcat记录的内容是**“I am original”**,说明数据内容没有保存,这也和先前的实验形成了对比,也说明了saveinstantstate处理系统自行运行onDestroy而导致数据丢失的功能;
    在这里插入图片描述

  17. 接下来就是通过实验说明活动的standard, singleTop, singleTask和singleInstance四种启动模式之间的区别点;首先我们对活动一的代码进行修改,让它变回原来的跳转到活动2的功能,同时添加代码来记录活动本身的相关信息;并追加一个新的按钮,来实现活动1跳转到他自身;在Manifest中也对启动模式进行修改,首先设置为standard来进行实验;

    package com.example.test;
    
    import androidx.appcompat.app.AppCompatActivity;
    import android.content.Intent;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    
    public class MainActivity extends AppCompatActivity {
        public String TAG="main";
        protected void onDestroy() {
            super.onDestroy();
            Log.d(TAG,"onDestory");
        }
    
        @Override
        protected void onStart() {
            super.onStart();
            Log.d(TAG,"onStart");
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            Log.d(TAG,"onResume");
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            Log.d(TAG,"onPause");
        }
    
        protected void onStop(){
            super.onStop();
            Log.d(TAG,"onStop");
        }
    
        protected void onRestart(){
            super.onRestart();
            Log.d(TAG,"onRestart");
        }
    
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Log.d(TAG,"onCreat");
            setContentView(R.layout.activity_main);
            Log.d("main",this.toString());     //对活动相关信息进行记录
            Button button=(Button) findViewById(R.id.button_1);
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent=new Intent(MainActivity.this,Main2Activity.class);  //跳转到活动2;
                    startActivity(intent);
                }
            });
            Button button1=(Button) findViewById(R.id.button_3);
            button1.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent=new Intent(MainActivity.this,MainActivity.class);  //跳转到活动1自身;
                    startActivity(intent);
                }
            });
        }
    }
    
    
<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".Main2Activity"></activity>
    <activity android:name=".MainActivity"
        android:launchMode="standard">   //设置启动模式
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>	
</application>
  1. 在standard模式下打开APP,这种模式下,当Intent发送的时候,Activity总是被创建一个新的出来单独工作,也就是说每实现一次跳转,都会产生新的Activity;我们连续地点击Goto Myself来实现活动1跳转到它本身,同时我们对logcat的内容进行观察;
    在这里插入图片描述

  2. 通过logcat我们可以看到在我点击Goto Myself时,每点击一次他都会产生一个新的Activity,这里我点击了三次,也产生了三个新的Activity;

    这样我们就对standard模式有了一个直观的了解,每次Intent发送的时候,总是会创建一个新的Activity出来;
    在这里插入图片描述

  3. 接下来来试一下singleTop,它的表现几乎和standard模式一模一样,一个singleTop Activity 的实例可以无限多,唯一的区别是如果在栈顶已经有一个相同类型的Activity实例,Intent不会再创建一个Activity,而是通过onNewIntent()被发送到现有的Activity。

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".Main2Activity"></activity>
        <activity android:name=".MainActivity"
            android:launchMode="singleTop">   //设置启动模式
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    
  4. 同样,我们也采用连续地点击Goto Myself来实现活动1跳转到它本身,同时我们对logcat的内容进行观察;可以看到当我点击Goto Myself时,出现了onPause和onResume却并没有新的Activity产生,这是因为活动1就在栈顶,而singleTop模式下如果在栈顶已经有一个相同类型的Activity实例,Intent不会再创建一个Activity;而接下来我点击Goto Activity2,再在活动2中点击Goto Activity1来实现两个活动的相互跳转,这是logcat的内容就不一样了,我实现了两次相互跳转,同时它也生成了两个新的Activity1,这是因为跳转到活动2时,活动1并不位于栈顶,所以发送intent后会产生一个新的Activity;
    在这里插入图片描述

  5. 而singleTask与之前两个就不太相同,singleTask模式的Activity只允许在系统中有一个实例。如果系统中已经有了一个实例,持有这个实例的任务将移动到顶部,同时intent将被通过onNewIntent()发送。如果没有,则会创建一个新的Activity并置放在合适的任务中。也就是说,无论活动在栈中的哪个位置,都只会存在一个Activity实例,并不会重复产生新的Activity实例;

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".Main2Activity"></activity>
        <activity android:name=".MainActivity"
            android:launchMode="singleTask">   //设置启动模式
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    
  6. 对singleTask验证的方法就是采取活动1和活动2之间的相互跳跃,来查看是否有新的Activity实例产生;从logcat中可以看出至始至终都没有新的Activity产生,这也体现出了singleTask模式下的特点;
    在这里插入图片描述

  7. 最后就是singleInstance模式(单实例模式),是一种加强的singleTask模式,它除了具有singleTask模式的所有特性以为,还加强了一点:具有此种模式的activity只能单独地位于一个任务栈中,比如activity A是singleInstance模式,当A启动后,系统会为它创建一个新的任务栈,然后A独自在这个新的任务栈中,由于栈内复用的特性,后续的请求均不会创建新的activity,除非这个独特的任务栈被系统销毁了;activity会启动一个新的任务栈来管理这个activity,singleInstance模式加载activity时,无论从哪个任务栈中启动该activity,只会创建一个activity实例,并且会使用一个全新的任务栈来装载该activity实例

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".Main2Activity"></activity>
    <activity android:name=".MainActivity"
        android:launchMode="singleInstance">   //设置启动模式
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>
  1. 因为singleInstance模式下会启动一个新的任务栈来管理activity,所以无论是在活动1中点击Goto Myself还是在活动2中点击Goto Activity1都不会产生新的Activity实例,它会运行在自己单独,独立的任务栈里面,并且任务栈里面只有这一个实例存在;也就是说整个系统中只会存在一个这样的实例,因为它拥有着自己独立的任务栈,与其他Activity分离;
    在这里插入图片描述
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值