zoukankan      html  css  js  c++  java
  • Android:Activity 机制与生命周期

    Activity 组件

    组件是 Android 应用程序的重要基石,每一个 Android 应用程序均是由若干个组件组成的。Android 中有 Activity、Service、Broadcast Receiver、Content Provider 四种不同类型的应用组件,每一类组件都是独立的实体,拥有不同的生命周期。
    界面是应用程序与客户打交道的最直接最常用的途径,Activity 是提供屏幕界面来实现与用户交互的应用组件。Activity 是活动的意思,一个 Activity 一般代表手机上的一屏,是 Androi 程序的可视化界面窗口。Activity 可容纳控件、菜单等界面元素,能够响应所有的窗口事件,实现用户交互。
    在一个应用程序可以有多个 Activity,它们构成了 Activity 栈,当前活动的 Activity 位于栈顶,上一个 Activity 被压入栈成为非活动的 Activity。Activity 之间可互相跳转,进行数据传递。为了保持界面状态,需要管理 Activity 生命周期、转跳逻辑以及持久化操作。

    Activity 的状态与生命周期

    Activity 在不同的周期运行不同的函数,处于不同的状态,Activity 具有以下 4 种状态。

    状态 说明
    活动/运行状态 当前运行的 Activity,处于栈的最顶端,用户可见且能获得焦点。
    暂停状态 Activity 失去焦点,仍然可见但不能与用户交互。当内存资源不足时,不能被系统 killed。
    终止状态 Activity 被完全覆盖,在屏幕上不可见,但仍然保留有信息。当内存资源不足时,能被系统 killed。
    销毁状态 Activity 被系统销毁回收或者没有被启动

    在 Activity 的生命周期中,不同状态的切换会调用一系列回调方法(Callback)。通过重写这些方法,应用程序可以实现业务逻辑功能。

    回调方法 说明
    onCreate() Activity 首次被创建时调用,完成初始化工作,多用于创建视图、为列表绑定数据
    onStart() 当 Activity 即将变成用户可见的视图时被调用
    onResume() 在 Activity 开始与用户交互之前被调用,位于栈的顶部可以接受用户输入
    onPause() 要启动另一个Activity时,调用这个方法暂停当前的 Activity 并保存它的状态数据
    onStop() Activity 对于用户不可见时调用
    onDestroy() 在 Activity 销毁前调用,发生在 finish() 方法执行时,或者系统因为空间不足而临时销毁
    onRestart() 当 Activity 停止后再次启动之前被调用

    创建 Activity

    创建一个 Activity 一般是继承 android.app 包中的 Activity 类,也可以根据需要继承 Activity 的子类。

    import android.app.Activity;
    
    public class MainActivity extends Activity{
    
    }
    

    接着需要重写要用的 callback 方法,通常情况下至少要重写 onCreate() 方法,并且调用 setContentView() 方法设置要显示的页面。例如现在创建一个 Activity,重写 onCreate() 方法设置要显示的页面为 activity_main.xml 的代码如下。

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    

    在 Android Studio 创建 Activity 非常方便,只需要选中对应的包然后右键选择 “New”,选中 “Activity” 之后即可进行创建。

    实验:观察 Activity 生命周期

    实现思路

    想要在用户不同的行为下,观察到 Activity 所处于的生命周期阶段和分别执行的回调方法有 2 种实现的思路。第一种是在调用不同的方法时显示不同的提示信息,第二种是使用日志进行查看。

    Toast 类

    第一种实现方法可以使用 Toast 类输出提示信息,Toast 是一种简易的消息提示框,用户不能直接操作这个提示框,且显示的时间有限,Toast 的提示信息可以在调试程序的时候方便的显示某些想显示的东西。想要使用 Toast 类,需要导入 android.widget.Toast。

    import android.widget.Toast;
    

    想要创建 Toast 对象,可以使用 makeText() 方法,创建完 Toast 对象后,可以使用 show() 方法显示提示信息。

    makeText(Context context, int resId, int duration)
    makeText(Context context, CharSequence text, int duration)
    
    参数 类型 说明
    context Context 当前的上下文环境,可用 getApplicationContext() 或 getContext() 或 this
    text/resId CharSequence/ int 要显示的字符串,可以是 R.string 中字符串 ID
    duration int 显示的时间长短

    Log 类

    第二种就是使用日志,可以使用 Android 系统为开发者提供的良好的日志工具 android.util.Log

    import android.util.Log;
    

    常用的方法有 5 个,其中可以使用 Log.d("Tag","Msg") 方法来输出 Debug 调试信息。当某个方法被调用时,android studio 可以在 LogCat 中看到日志信息。

    方法 说明
    Log.v() 打印琐碎的、意义最小的日志信息,对应级别 verbose,Android 日志里级别最低
    Log.d() 打印一些程序调试信息,对应级别 debug,比 verbose 高一级
    Log.i() 打印一些比较重要的数据,用于分析用户行为,对应级别 info,比 debug 高一级
    Log.w() 打印一些警告信息,提示程序在这个地方可能会有潜在的风险,对应级别 warn,比 info 高一级
    Log.e() 打印程序中的错误信息,代表较为严重的问题,必须尽快修复,对应级别error,比 warn 高一级

    代码实现

    首先需要创建一个 Activity,然后设置一个成员变量 state 存储要显示的提示信息。

    private String state = "";
    

    然后编写一个 showState() 方法用于生成提示信息,并且显示在界面中。

    private void showState(){
        // new Throwable().getStackTrace()返回当前运行栈的结构,获得调用类和方法名
        String strState = new Throwable().getStackTrace()[1].getMethodName()
                 + ":" + new Throwable().getStackTrace()[2].getMethodName();
        //把 Exception 信息存放到一个字符串 strState 里
        state = state + strState + "-->
    ";
        //实例化一个 Toast 类,并设置位置后显示
        Toast toast = Toast.makeText(getApplicationContext(), state, Toast.LENGTH_LONG);
        toast.setGravity(Gravity.TOP, 0, 200);
        toast.show();
    }
    

    接着只需要在每个 callback 方法中调用 showState() 方法和 Log.d("Tag","Msg") 方法时,就可以分别在界面和 LogCat 中看到提示信息。

    @Override
    public void onStart(){
        super.onStart();
        showState();
        Log.d(StringTAG, "onStart()");
    }
    

    运行测试

    启动 Activity

    首先在启动 Activity,可以看到调用了 onCreate()、onStart() 和 onResume() 3 个方法,onCreate() 方法在首次创建 Activity 时被调用,用于初始化。onStart() 在 Activity 变成用户可见的视图时被调用,onResume() 在 Activity 与用户开始交互前被调用。

    页面切出

    当页面被切出时,可以看到调用了 onPause() 和 onStop() 方法。onPause() 用于暂停当前的 Activity 并保存它的状态数据,onStop() 方法用于在 Activity 不可见时被调用。

    页面切回来

    当页面重新切回来时,调用了 onRestart()、onStart() 和 onResume() 3
    个方法。

    关闭应用

    最后当关闭应用时,调用了 onPause()、onStop() 和 onDestroy() 方法,onDestroy() 方法在 Activity 被销毁时被调用,或者当系统空间不足需要销毁 Activity 时被调用。

    屏幕转向

    接下来当手机屏幕横向纵向转换时,可以看到先调用了 onPause()、onStop()和 onDestroy()方法,接着调用了 onCreate()、onStart() 和onResume() 3 个方法。

    这个过程是由于用户屏幕转向时,相当于 Activity 页面的呈现发生了改变需要重新构建,因此经历了 Activity 被销毁后重建的过程。

    接收到短信

    接下来需要模拟手机接收短信,在 android studio 中可以使用 Extended Controls 中的 Phone 选项生成短信并发送。


    当 Activity 运行时手机突然收到短信,打开短信界面,看完短信后返回原来的 Activity。可以看到查看短信时调用了 onPause() 和 onStop() 方法。


    查看短信后切回页面,调用了 onRestart()、onStart() 和 onResume() 3
    个方法。注意此时切屏时并没有调用 onDestroy() 方法,这是因为查看短信时原来的页面并没有被完全销毁,而是被完全遮盖了,所以并没有 Activity 被销毁后重建的过程。

    完整代码

    package com.example.myapplication;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.os.Bundle;
    import android.view.Gravity;
    import android.widget.Toast;
    import android.util.Log;
    
    public class MainActivity extends AppCompatActivity {
        private String state = "";
        private static final String StringTAG = "MainActivity";
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            showState();
            Log.d(StringTAG, "onCreate()");
        }
    
        private void showState(){
            String strState = new Throwable().getStackTrace()[1].getMethodName()
                    + ":" + new Throwable().getStackTrace()[2].getMethodName();
            state = state + strState + "-->
    ";
            Toast toast = Toast.makeText(getApplicationContext(), state, Toast.LENGTH_LONG);
            toast.setGravity(Gravity.TOP, 0, 200);
            toast.show();
        }
    
        @Override
        public void onStart(){
            super.onStart();
            showState();
            Log.d(StringTAG, "onStart()");
        }
    
        @Override
        public void onRestart(){
            super.onRestart();
            showState();
            Log.d(StringTAG, "onRestart()");
        }
    
        @Override
        public void onResume(){
            super.onResume();
            showState();
            Log.d(StringTAG, "onResume()");
        }
    
        @Override
        public void onPause(){
            super.onPause();
            showState();
            Log.d(StringTAG, "onPause()");
        }
    
        @Override
        public void onStop(){
            super.onStop();
            showState();
            Log.d(StringTAG, "onStop()");
        }
    
        @Override
        public void onDestroy(){
            super.onDestroy();
            showState();
            Log.d(StringTAG, "onDestroy()");
        }
    }
    

    参考资料

    《零基础学 Android》,明日科技编著,吉林大学出版社
    《Android 移动应用开发》,杨谊 主编、喻德旷 副主编,人民邮电出版社
    toast用法
    Android util.Log 工具类

  • 相关阅读:
    性能测试1 概述
    CURRENMONTH TAG in Automation Framework
    [luoguP1076] 寻宝(模拟)
    [luoguP1220] 关路灯(DP)
    [luoguP1373] 小a和uim之大逃离(DP)
    [HDU2089] 不要62 (数位DP)
    [luoguP1095] 守望者的逃离(DP)
    [luoguP1156] 垃圾陷阱(DP)
    [luoguP1736] 创意吃鱼法(DP)
    [luoguP1417] 烹调方案(背包DP)
  • 原文地址:https://www.cnblogs.com/linfangnan/p/15341195.html
Copyright © 2011-2022 走看看