【移动安全技术】_第三站_Activity的生命周期



作业:活动的生命周期和启动

  1、通过在不同的活动之间的转换,观察onCreate, onStart, onResume, on Pause, onStop,onDestroy以及onRestart函数的调用情况。
  2、通过实验说明存在系统可能自行对活动运行onDestroy。
  3、利用saveinstantstate处理系统自行运行onDestroy而导致数据丢失的情况
  4、通过实验说明活动的standard, singleTop, singleTask三种启动模式之间的区别点。

  附加题:说明活动singleInstance启动模式的功能

  评分标准:所有实验都完成起评为85分,附加题5分。其它分数增减根据报告情况



理论知识

返回栈

  我们可以看到,Android的活动是层叠嵌套的,启动新活动会覆盖在原活动之上,点击back会销毁最上面的活动,下面紧跟的活动就会重新显示出来。

  Android使用任务(Task)管理活动,一个任务就是存放在栈里的活动集合,这个栈也被称作返回栈(Back Stack)。


活动状态

  每个活动在其生命周期最多可能会有4种状态。

活动状态描述
运行状态活动位于栈顶
暂停状态活动不在栈顶,但仍然可见
停止状态活动不在栈顶,且完全不可见(即被覆盖)
销毁状态活动被返回栈移除
活动的生存期

  Activity类中定义了7个回调方法,覆盖了活动生命周期的每一个环节。

活动的回调方法详细说明
onCreate()每个活动重写此方法,它在活动第一次被创建时调用。完成初始化操作,如加载布局、绑定事件等
onDestroy()在活动销毁之前被调用,此后活动状态将变成销毁状态
onResume()活动即将与用户交互,此时活动那个位于栈顶,处于运行状态
onPause()在系统准备启动或者恢复另一个活动时调用
onStart()在活动由不可见变成可见时调用
onStop()在活动完全不可见的时候调用
onRestart()活动由停止状态变成运行状态之前调用
活动的启动模式

  实际项目中,需要根据特定的需求为每个活动指定恰当的启动模式。

  启动模式有四种,分别是standard、singleTop、singleTask 和 singleInstance。
通过Manifest.xml仓库文件的<activity>标签指定android:launchMode属性选择启动模式。

  活动的默认启动模式是standard,在这个模式下,每次启动一个新的活动,它就会在返回栈中入栈并处于栈顶,系统不在乎这个活动已经在返回栈中存在,而是创建该活动的一个新的实例。

  当活动位于栈顶时,我们完全没必要新建一个活动实例,所以在启动活动时检查栈顶,如果栈顶已经是该活动,则直接使用该栈顶实例。这种启动模式称为singleTop。

  但其实返回栈存在活动实例时,我们完全没必要新建一个活动实例,所以在启动活动时检查返回栈,如果返回栈已经有该活动,则直接使用该返回栈实例。这种启动模式称为singleTask。

  



实验过程

创建活动并编写代码

  创建主活动后,需要分别再创建两个子活动:normalActivity和dialogActivity。因为子活动分为完全覆盖和部分覆盖,两种情况对应的主活动状态是不同的。

  本部分概述:主活动MainActivity.java,定义两个按钮进行页面跳转,重写7个回调函数并嵌套Log.d()函数,用于打印和观察主活动所处的生命周期。

  布局文件activity_normal.xml:

<LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">
    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="this is normal_activity"
        />
    </LinearLayout>

  布局文件activity_dialog.xml:

<LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="this is dialog_activity"
         />

    </LinearLayout>

  在Manifest.xml仓库文件中注册dialog活动,设置为对话框式主题:

<activity android:name=".dialog"
	android:theme="@style/Theme.AppCompat.Dialog"
	></activity>
	
<activity android:name=".normalActivity" />

  主活动MainActivity.java:

public class MainActivity extends AppCompatActivity {

    public static final String TAG = "MainActivity" ;   // 定义字符串变量,用于提示主活动
   
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d(TAG,"onCreate");

        Button button_normal = (Button) findViewById(R.id.button_normal);
        button_normal.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, normalActivity.class);
                startActivity(intent);
            }
        });

        Button button_dialog = (Button) findViewById(R.id.button_dialog);
        button_dialog.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent_dialog = new Intent(MainActivity.this, dialog.class);
                startActivity(intent_dialog);

            }
        });

    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG,  "onResume");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "onPause");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.d(TAG, "onStop");
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.d(TAG, "onStart");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Log.d(TAG, "onRestart");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy");
    }
}


  效果图:

在这里插入图片描述

图一:主活动

在这里插入图片描述

图二:normal活动

在这里插入图片描述

图三:dialog活动


1.通过活动转换观察7个回调函数的使用情况
点击操作Logcat界面显示说明
操作一-见图二
点击跳转normal页面出现onPause和onStop主页面暂停,且不可见
返回到主页面onRestart、onStart、onResume重新启动、可见、交互运行
操作二-见图三
点击跳转dialog页面出现onPause主页面暂停
返回到主页面onResume重新启动
操作三-见图四
点击返回退出程序出现onPause、onStop、onDestroy系统

在这里插入图片描述

图一:启动主页面

在这里插入图片描述

图二:点击按钮跳转normal页面并返回

在这里插入图片描述

图三:点击按钮跳转dialog页面并返回

在这里插入图片描述

图四:在主页面点击返回,退出安卓程序,系统自动销毁主页面


2.通过实验说明存在系统可能自行对活动运行onDestroy

  活动进入停止状态时,系统可能因为内存不足销毁回收该页面。

  场景:用户在活动A的基础上启动了活动B,此时系统回收活动A,用户点击Back键返回活动A,此时会执行活动A的onCreate()方法。

  存在问题:活动A可能存在临时数据和状态,比如用户正在活动A输入文字,突然弹出一个活动B,此时用户的输入会被清空。

  解决办法:Activity提供onSaveInstanceState()回调方法,该方法在活动回收前一定会被调用,因此可以通过这个方法来保存临时数据。

  由于实验环境下的系统内存相对充足,在normal页面停留十分钟,系统仍然没有销毁主页面,所以这部分没有截图。


3.利用saveinstantstate保存临时数据

  在MainActivity.java中添加onSaveInstanceState()函数代码,在onCreate()函数代码中添加 if()语句:

protected void onSaveInstanceState(Bundle outState){

        super.onSaveInstanceState(outState);
        outState.putString("data_key", tmpdata);
    }
 
onCreate()函数代码: 
		super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if(savedInstanceState != null){
            String tmpdata = savedInstanceState.getString("data_key");
            Log.d(TAG, tmpdata);
        }


4.说明活动的standard, singleTop, singleTask三种启动模式之间的区别点

standard

实验代码
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d("FirstActivity", this.toString());	// 打印本实例信息
        

        Button button_normal = (Button) findViewById(R.id.button_normal);
        button_normal.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, MainActivity.class);
                startActivity(intent);
            }
        });
    }
}

  点击按钮,使页面跳转到自己,观察Logcat窗口,可以发现每点击一次,就会产生一个新的实例,而我们需要点击对应次数的back才能退出程序:

在这里插入图片描述

singleTop

实验代码
在仓库文件中为当前主活动添加启动模式,主活动代码与standard保持不变:
<activity android:name=".MainActivity"
          android:launchMode="singleTop">

  此时点击,程序不会生成主活动的新实例。但如果该活动实例不在栈顶,比如在Second活动的基础上跳转到主活动,那么还会生成主活动的新实例。

singleTask

实验代码
在仓库文件中为当前主活动添加启动模式,主活动代码与standard保持不变:
<activity android:name=".MainActivity"
          android:launchMode="singleTask">

  



报错gradle project sync failed

  原因:在仓库文件Manifest.xml空白行添加了注释: //四种启动模式

  解决办法:删掉Manifest.xml文件中的注释。



反思

  问题:课上跟着教授做一遍,课后跟着参考书籍又梳理一遍,时间欠费了。

  解决办法:课上边听边梳理,整理好理论知识、准备好实验代码,等待任务发布。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值