Activity的生命周期

news2025/7/8 2:53:48

文章目录

  • Activity的生命周期
    • 一.返回栈
    • 二.Activity状态
      • 1.运行状态
      • 2.暂停状态
      • 3.停止状态
      • 4.销毁状态
    • 三.Activity的生存期
      • onCreate()
      • onStart()
      • onResume()
      • onPause()
      • onStop()
      • onDestroy()
      • onRestart()
      • 完整生存期
      • 可见生存期
      • 前台生存期
      • Activity的生命周期图
      • 体验Activity的生命周期
        • 编写三个对应的Activity
      • Activity被回收了怎么办
        • onSaveInstanceState()方法

Activity的生命周期

一.返回栈

  • 在Android当中Activity是可以进行重叠的,我们每次启动一个新的Activity,就会覆盖在原先的Activity之上,然后点击Back键就会销毁最上面的Activity,下面的Activity就会显示出来.
  • 在Android当中使用任务(task)来管理Activity,一个任务就是一组存在栈里的Activity的集合,这个栈也被称作为返回栈(back stack)
  • 当我们启动一个新的Acticity的时候,这个Activity就会处于这个返回栈的栈顶,当我们点击back销毁一个栈的时候,就会将栈顶的Activity进行出栈

.

二.Activity状态

  • 每个Activity在其生命周期中最多可能会存在4中状态:运行状态,暂停状态,停止状态,销毁状态

1.运行状态

  • 当一个Activity位于返回栈的栈顶的时候,Activity就会存在运行状态.

2.暂停状态

  • 当一个Activity不在处于栈顶,但是它又是可见的情况下,Activity就进入了暂停状态.
  • 既然Activity已经不在栈顶的位置了,那为什么还是可见的呢?因为并不是每一个Activity都会占满整个屏幕,比如对话框形式的Activity只会占用屏幕中间的部分
  • 处在暂停状态的Activity仍然是完全存活的,系统也不愿意去回收这种类型的Activity,因为直接回收可见的Activity就相当于页面直接消失了内容,这种情况十分影响用户的体验.
  • 只有在内存极低的情况下才会考虑回收这种类型的Activity

3.停止状态

  • 当一个Activity不再处于栈顶的位置,而且完全不可见的情况下,这个时候Activity就进入了停止状态.
  • 系统仍然会给这种Activity保存相应的状态和成员变量,但是这种是不太靠谱的,因为当有其他地方需要内存但是内存不够用的情况下,就会将这种Activity进行回收.

4.销毁状态

  • 一个Activity从栈中移除之后,就变成了销毁状态,系统最倾向于回收处于这种状态的Activity,以此来保证手机内存的充足.

三.Activity的生存期

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

onCreate()

  • 该方法会在Activity第一次被创建的时候进行调用,在该方法当中可以完成对Activity的初始化,比如加载布局,绑定事件等等.

onStart()

  • 这个方法在Activity中由不可见变为可见的时候进行调用

onResume()

  • 这个方法用于Activity准备好和用户进行交互的时候进行调用.此时的Acticity一定位于返回栈的栈顶位置,并且处在运行状态.

onPause()

  • 这个方法在系统准备去启动或者恢复另外一个Activity的时候进行调用.我们通常会在这个方法当中将一些消耗CPU的资源释放掉,以此来保存一些关键性的数据,但是这个方法的执行速度一定要快,不然会影响到新的栈顶Activity的使用.

onStop()

  • 这个方法在Activity完全不可见的时候进行调用,它和onPause()方法的区别在于,如果启动的新Activity是一个对话框式Activity,那么onPause()方法会得到执行,而onStop()方法不会被执行

onDestroy()

  • 这个方法在Activity被销毁之前进行调用,之后Activity的状态将变成为销毁状态

onRestart()

  • 这个方法在Activity由停止状态变为运行状态之前进行调用,也就是说Acticity被重新进行启动了

在以上的七个方法当中,除了onRestart()方法,其他都是两两相对的,从而可将Activity分成以下三种生存期

完整生存期

  • Activity在onCreate()方法和onDestroy()方法之间所经历的就是完整生存期,一般情况下,Activity会在onCreate()方法中完成各种初始化的操作,在onDestroy()方法当中完成释放内存的各种操作.

可见生存期

  • Activity在onStart()和onStop()方法之间经历的过程就是可见生存期,在可见生存期当中,Activity对于用户总是可见的.
  • 即便可能无法和用户进行直接的交互,但是通过这两方法可以合理的管理那些对用户可见的资源
  • 比如在onStart()方法中对资源进行加载,在onStop()方法当中对资源进行释放.从而保证处于停止状态的Activity不会占用过多的内存

前台生存期

  • Activity在onResume()方法和onPause()方法之间的经历就是前台生存期
  • 在前台生存期内Activity总是处在运行状态,此时Activity是可以和用户进行交互的

Activity的生命周期图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KsfwGtIU-1669176292470)(C:/Users/zhengbo/%E6%88%91%E7%9A%84%E5%AD%A6%E4%B9%A0/Typora%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/%E5%AE%89%E5%8D%93/image-20221123015422283.png)]

体验Activity的生命周期

编写三个对应的Activity

normal_activity

<?xml version="1.0" encoding="utf-8"?>
<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:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="This is a dialog activity" />

</LinearLayout>
package com.zb.activitylifecycletest

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle

class NormalActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.normal_layout)
    }
}

dialog_activity

<?xml version="1.0" encoding="utf-8"?>
<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:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="This is a dialog activity" />

</LinearLayout>
package com.zb.activitylifecycletest

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle

class DialogActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.dialog_layout)
    }
}

在AndroidManifest.xml中设置DialogActivity的主题为对话框式的主题

        <activity
            android:name=".DialogActivity"
            android:theme="@style/Theme.AppCompat.Dialog"
            android:exported="false" />
        <activity

main_activity

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/startNormalActivity"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Start NormalActivity" />

    <Button
        android:id="@+id/startDialogActivity"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Start DialogActivity" />

</LinearLayout>
package com.zb.activitylifecycletest

import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {
    private val tag = "MainActivity"
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.d(tag, "onCreate")
        setContentView(R.layout.activity_main)
        startNormalActivity.setOnClickListener {
            val intent = Intent(this, NormalActivity::class.java)
            startActivity(intent)
        }
        startDialogActivity.setOnClickListener {
            val intent = Intent(this, DialogActivity::class.java)
            startActivity(intent)
        }
    }

    override fun onStart() {
        super.onStart()
        Log.d(tag, "onStart")
    }

    override fun onResume() {
        super.onResume()
        Log.d(tag, "onResume")
    }

    override fun onPause() {
        super.onPause()
        Log.d(tag, "onPause")
    }

    override fun onStop() {
        super.onStop()
        Log.d(tag, "onStop")
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.d(tag, "onDestroy")
    }

    override fun onRestart() {
        super.onRestart()
        Log.d(tag, "odRestart")
    }
}
  • 在MainActivity中的onCreate方法中设置了两个点击事件,点击第一个按钮会启动NormalActivity,点击第二个按钮会启动DialogActivity,然后再Activity的7个回调方法中分别用日志输出相关的内容
  • 这样就可以通过观察日志的方法老观察Activity的生命周期了.

Activity被回收了怎么办

  • 当一个Activity进入了停止状态,是有可能会被系统回收的.
  • 假如现在一个应用当中有一个ActivityA,用户在ActivityA的基础上启动了ActivityB,那么ActivityA就进入了停止状态,这个时候由于系统内存空间不足,将Activity回收掉了
  • 然后用户按下Back键后,其实还是会正常进行显示的,只不过就是这个时候并不会调用onRestart()方法,而是会执行ActivityA的onCreate()方法,因为在这种情况下Activity需要被重新创建一次
  • 但是存在一个重要的问题不能够忽略:ActivityA中是有可能存在临时数据和状态的.当这个Activity由于内存不足被回收了会导致临时数据造成丢失.
  • 如果我们的应用造成了临时数据的丢失实际上是比较影响用户体验的,所以需要我们想想办法来解决这个问题
  • 在Activity中还提供了一个方法叫做onSaveInstanceState()回调方法,这个方法可以保证在Activity被回收之前一定会被调用,因此可以通过这个方法来解决问题.

onSaveInstanceState()方法

  • 该方法会携带一个Bundle类型的参数,Bundle提供了一系列的方法用来保存数据,比如可以使用putString()方法来保存字符串,putInt()来保存整形数据.
  • 每个保存数据的方法都采用键值对的方式,一个参数是键,用于后面从Bundle中取值,第二个参数就是我们要保存的值
  • 在MainActivity中重写onSaveInstanceState()方法
    //在Activity被回收之前保存相关数据
    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        val tempData = "Something you just typed"
        outState.putString("data_key", tempData)
    }
  • 这个时候数据已经保存下来了,那我们应该在那里进行数据的恢复呢?
  • 其实在我们一直使用的onCreate()方法的参数当中就有一个Bundle类型的参数,一般情况下这个参数都是为null的,但是当Activity被系统回收之前,开发人员通过onSaveInstanceState()方法保存的数据之后,onCreate()方法这个参数就会带有之前保存的全部数据.然后我们只需要通过相应的方法取出我们保存的值即可
  • 在onCreate()方法中通过Bundle参数取出保存的数据
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        if (savedInstanceState != null) {
            val tempData = savedInstanceState.get("data_key")
            Log.d(tag, "tempData is $tempData")
        }
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/28703.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PTA题目 阅览室

天梯图书阅览室请你编写一个简单的图书借阅统计程序。当读者借书时&#xff0c;管理员输入书号并按下S键&#xff0c;程序开始计时&#xff1b;当读者还书时&#xff0c;管理员输入书号并按下E键&#xff0c;程序结束计时。书号为不超过1000的正整数。当管理员将0作为书号输入时…

机器人工程考研难易主观感受和客观数据

简易版&#xff08;共性&#xff09;&#xff1a; 主观反馈&#xff1a;越来越难 客观数据&#xff1a;研究生录取人数越来越多&#xff0c;比例也越来越高 看起来矛盾&#xff0c;其实并非如此。 详细数据&#xff1a; 80后是指1980年至1989年出生的人口&#xff0c;对应2…

MySQL_07:单行函数

文章目录一、函数的基本理解1.函数的理解1.1内置函数的基本理解1.2不同DBMS函数的差异1.3MySQL的内置函数的分类2.图解多行函数和单行函数二、单行函数1.数值函数1.1基本函数1.2角度与弧度互换函数1.3三角函数1.4指数与对数1.5进制间转换2.字符串函数3.日期和时间函数3.1获取日…

python常用操作之使用多个界定符(分隔符)分割字符串

本系列文章会总结python中各种常见及常用的内置方法、对不同数据结构的操作&#xff0c;参考书籍《python cookbook》第三版 分割字符串单个界定符分割字符串代码演示多个界定符分割字符串代码演示注意总结在日常学习及工作中&#xff0c;不论是在解析数据还是在产出输出&#…

【LeetCode】No.98. Validate Binary Search Tree -- Java Version

题目链接&#xff1a;https://leetcode.com/problems/validate-binary-search-tree/ 1. 题目介绍&#xff08;Validate Binary Search Tree&#xff09; Given the root of a binary tree, determine if it is a valid binary search tree (BST). 【Translate】&#xff1a; 给…

Qt 堆栈窗体QStackedWidget使用

QStackedWidget控件相当于一个容器&#xff0c;提供一个空间来存放一系列的控件&#xff0c;并且每次只能有一个控件是可见的&#xff0c;即被设置为当前的控件。QStackedWidget可用于创建类似于QTabWidget提供的用户界面。 它是一个构建在QStackedLayout类之上的方便布局小部件…

dolphinscheduler 2.0.6 负载均衡源码

目录&#x1f42c;官网介绍&#x1f42c;负载均衡&#x1f420;加权随机&#xff08;random&#xff09;&#x1f420;平滑轮询&#xff08;roundrobin&#xff09;&#x1f420;线性负载&#xff08;lowerweight&#xff09;&#x1f435;其它&#x1f42c;官网介绍 官网资料&…

【计算机网络】网络层:虚拟专用网

由于IP地址的紧缺&#xff0c;一个机构能够申请到的IP地址数往往远小于本机构拥有的主机数。 如果一个机构内部的计算机通信也采用TCP/IP协议&#xff0c;那么这些仅字机构内部使用的计算机就可以由本机构自行分配其IP地址。 本地地址&#xff08;专用地址&#xff0c;互联网对…

Java培训教程给bean的属性赋值

依赖注入的方式 1. 通过bean的setXxx()方法赋值 Hello World中使用的就是这种方式 2. 通过bean的构造器赋值 Spring自动匹配合适的构造器<bean id“book” class“com.atguigu.spring.bean.Book” > <constructor-arg value “10010”/> …

有位p8终于把珍藏多年的算法视频给分享出来了,总共3.81G

大厂面试都开始问算法了&#xff0c;要是你不会算法只能与大厂失之交臂。为了解决大家算法方面的缺失&#xff0c;小编特此分享算法的学习路线和学习视频&#xff0c;希望大家能够喜欢&#xff01;&#xff01;&#xff01; 左神算法-KMP算法及其扩展 左神算法-Morris遍历及其…

S2B2C供应链系统将引领商业模式!S2B2C供应链电商系统实现订单管理数智化

近年来随着5G、人工智能、区块链、大数据、物联网等技术的快速发展&#xff0c;带动了数字经济的升级发展&#xff0c;疫情的不断反复更是加速推动了数字经济新发展&#xff0c;产业数字化和数字产业化进程加快&#xff0c;促进了各行各业快速发展&#xff0c;S2B2C供应链系统模…

17【redux】

17 【redux】 引言 我们现在开始学习了 Redux &#xff0c;在我们之前写的案例当中&#xff0c;我们对于状态的管理&#xff0c;都是通过 state 来实现的&#xff0c;比如&#xff0c;我们在给兄弟组件传递数据时&#xff0c;需要先将数据传递给父组件&#xff0c;再由父组件…

[附源码]Python计算机毕业设计大学生志愿者管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

软件工程经济学期末复习

1、利润 收入-成本费用 2、资产 流动资产非流动资产 3、显性成本可以用货币计量&#xff0c;是可以在会计的帐目上反映出来的 4、领取什么保险应缴纳个人所得税 商业保险 某企业一项固定资产的原价为800 0000元&#xff0c;预计使用年限为6年&#xff0c;预计净残值为5 0…

软件测试linux面试相关的知识

一、常用的命令 ls&#xff08;查看目录下的内容&#xff0c;-a显示隐藏目录&#xff09; cd&#xff08;进入某个目录&#xff0c;cd .. 返回上一层目录&#xff0c;cd - 返回上一次的目录&#xff0c;cd / 返回根目录&#xff09; pwd&#xff08;显示当前绝对路径&#x…

阿里云易立:以增效促降本,容器服务全面进入智能化时代

容器技术已经跨越鸿沟&#xff0c;广泛应用于金融、通讯、制造、交通等千行百业。Kubernetes支撑的工作负载也从早期单一的互联网应用发展到数据库、AI、大数据等等&#xff0c;并覆盖了公共云、专有云、边缘云等多样化、动态的云环境。 11月5日&#xff0c;2022杭州 云栖大会…

在Windows7在部署Hadoop+Hbase

0. 准备工作 0.1 电脑上现在没有jdk 0.1 提前准备好文件 1. 现在开始安装jdk 1.8.0_60 安装成功&#xff0c;没啥问题 小疑问&#xff1a;自动配置好了环境变量? 1.1 小记 在安装jdk的时候&#xff0c;有三种小工具&#xff0c;可以根据需要选择性安装 JDKjre源代码 虽…

牛客网语法篇练习基础语法(二)

1.牛牛正在给他的朋友们买电影票&#xff0c;已知一张电影票价是100元&#xff0c;计算 x 位朋友的总票价是多少&#xff1f; x int(input()) a x*100 print(a) 2.给定两个整数a和b (0 < a,b < 10,000)&#xff0c;计算a除以b的整数商和余数。 a,b map(int,input().…

【深入浅出Java并发编程指南】「剖析篇」Fork/Join框架的实战开发和原理探究指南

前提概述 Java 7开始引入了一种新的Fork/Join线程池&#xff0c;它可以执行一种特殊的任务&#xff1a;把一个大任务拆成多个小任务并行执行。 我们举个例子&#xff1a;如果要计算一个超大数组的和&#xff0c;最简单的做法是用一个循环在一个线程内完成&#xff1a; 算法原理…

使用Typora+EasyBlogImageForTypora写博客,无图床快速上传图片

Typora下载 Typora以前都是免费的&#xff0c;自去年开始竟然要收费&#x1f914;&#xff08;不过也能理解&#xff0c;毕竟真心好用&#x1f60a;&#xff09;&#xff0c;在这里给大家提供的是免费的版本&#xff08;免安装&#xff0c;下载即可使用&#xff09;&#xff0…