【Android】安卓四大组件之Activity(二)

前言

在这篇文章之前,我已经写过了一篇有关Activity的内容,是关于activity之间的页面跳转和数据传递,而这篇文章着重强调的是Activity中的有关生命周期的理解。

1、什么是生命周期?

在之前学习Java的时候,Java中的一个类的对象就涉及到了生命周期,包括它的生成、作用、回收等等。

在Android中也有差不多的生命周期的概念,是针对Activity的。

首先,给出安卓开发文档中对生命周期的介绍:了解 Activity 生命周期

在官方文档的基础上,我们来理解各个生命周期!

当用户浏览、退出和返回到您的应用时,应用中的 Activity 实例会在其生命周期的不同状态间转换,而为了在 Activity 生命周期的各个阶段之间导航转换,Activity 类提供六个核心回调:onCreate()onStart()onResume()onPause()onStop()onDestroy()。当 Activity 进入新状态时,系统会调用其中每个回调。

以下是官方文档对六大生命周期回调方法的简化视图:

2、onCreate()

2.1 基本解析

因为生命周期是从上向下执行的,我们首先分析最开始的onCreate()方法

onCreate(),这个是activity被首次创建的时候调用的方法,而且我们必须在每个activity中重写该方法!这个方法在activity生命周期中只出现一次,如果第二次出现,那么说明上一个activity已经调用了onDestroy()方法,被销毁了。

相信你对下面的代码不陌生,因为每个activity中都会有这样类似作用的代码!

  1. private TextView photo;
  2. private ImageView pic;
  3. @Override
  4. protected void onCreate(@Nullable Bundle savedInstanceState) {
  5. super.onCreate(savedInstanceState);
  6. setContentView(R.layout.activity_camera);
  7. photo = this.findViewById(R.id.tv_photograph);
  8. pic = this.findViewById(R.id.iv_pic);
  9. photo.setOnClickListener(this);
  10. }

在开始构建activity的时候,我们在onCreate()方法中我们都会会将数据绑定到列表,将 Activity与各个组件相关联,并实例化某些类作用域变量。

我们在上述的代码例子中可以发现,我们实例化了photo这个TextView还有pic这个ImageView,并且在此之前,我们一定会给当前这个activity绑定一个xml布局文件,通过调用setContentView()方法,然后通过R.layout找到我们需要的布局xml进行绑定。

2.2 你可能疑惑的savedInstanceState

以下内容感兴趣的可以看看,初学者如果不明白其实也不需要太懂。

细心的你会发现,onCreate()其实传入了一个Bundle类的对象参数savedInstanceState,这是个啥玩意?

接下来,我们对savedInstanceState进行详细解释!

首先我们分析以下Bundle类是啥,说通俗一点,就是实现了Parcelable接口的一个键值对

官方的简介是:

A mapping from String keys to various Parcelable values.

也就是说,这个类实例化的对象是可以存储数据的,并且是以键值对的形式存储的,实现了Parcelable接口

而传入的savedInstanceState对象,字面翻译就是保存过的实例状态,并且我们上面说了,savedInstanceState都对象可以存储键值对,也就是说有两种情况:

  • savedInstanceState不为null
  • savedInstanceState是null的

事实上,savedInstanceState为null的情况是最常见的,但是什么情况savedInstanceState不为空呢?

2.2.1 onSaveInstanceState()方法

根据文档,我们发现,Activity类中有一个onSaveInstanceState()方法,不同于onCreate()这种生命周期方法,onSaveInstanceState()只有在进入某种“activity有被杀死的风险”的状态下,才会被调用

会执行onSaveInstanceState()方法的情况,官方文档中是如下解释的:

 Android calls onSaveInstanceState() before the activitybecomes vulnerable to being destroyed by the system, but does not bothercalling it when the instance is actually being destroyed by a user action (suchas pressing the BACK key).

当某个activity变得"容易"被系统销毁时,该activity的onSaveInstanceState()就会被执行,除非该activity是被用户主动销毁的,例如当用户按BACK键的时候。

通俗一点,就是进入某种“activity有被杀死的风险”状态,onSaveInstanceState()方法就会被调用

也许你想到了很多的情况,我总结了一共如下的情况会调用onSaveInstanceState()方法:

  • 当用户按下HOME键后。(这种情况,系统不知道你按下HOME后要运行多少其他的程序,自然也不知道activity A是否会被销毁,因此系统会调用onSaveInstanceState(),让用户有机会保存某些非永久性的数据)
  • 调出程序管理,选择运行其他的程序时。(同样是可能内存不够被系统kill掉)
  • 按下息屏键关闭屏幕时(一样的道理,手机厂家会设置息屏后进程的状态,也可能被kill)
  • 从activity A中启动一个新的activity B时。(例如从QQ打开某tx游戏,游戏的资源调用很大,可能把QQ的进程kill掉,虽然大多数情况我们是给QQ后台权限的)
  • 屏幕方向切换时,例如从竖屏切换到横屏时。(在屏幕切换时,系统会销毁activity A,在屏幕切换之后系统又会自动地创建activity A,所以onSaveInstanceState()一定会被执行,且也一定会执行onRestoreInstanceState()

说专业一点:只要某个Activity是做入栈并且非栈顶时(启动跳转其他Activity或者点击Home按钮),此Activity是需要调用onSaveInstanceState()的, 如果Activity是做出栈的动作(点击back或者执行finish),是不会调用onSaveInstanceState的。

2.2.2 onRestoreInstanceState()方法

onSaveInstanceState()对应的是onRestoreInstanceState()方法,但是——这两个方法并不是成对出现,执行了``onSaveInstanceState()不一定执行onRestoreInstanceState()`

onRestoreInstanceState()执行的条件是:只有在Activity真的被系统非正常杀死过,恢复显示Activity的时候,就会调用onRestoreInstanceState()

简单来说,执行了onSaveInstanceState()存储了数据状态,并不一定会调用onRestoreInstanceState()来返回状态,但是如果确实时非正常的kill进程,那么会调用onRestoreInstanceState()返回onSaveInstanceState()存储的数据

我们可以看看安卓开发文档中给出的例子:

  1. TextView textView;
  2. // some transient state for the activity instance
  3. String gameState;
  4. @Override
  5. public void onCreate(Bundle savedInstanceState) {
  6. // call the super class onCreate to complete the creation of activity like
  7. // the view hierarchy
  8. super.onCreate(savedInstanceState);
  9. // recovering the instance state
  10. if (savedInstanceState != null) {
  11. gameState = savedInstanceState.getString(GAME_STATE_KEY);
  12. }
  13. // set the user interface layout for this activity
  14. // the layout file is defined in the project res/layout/main_activity.xml file
  15. setContentView(R.layout.main_activity);
  16. // initialize member TextView so we can manipulate it later
  17. textView = (TextView) findViewById(R.id.text_view);
  18. }
  19. // This callback is called only when there is a saved instance that is previously saved by using
  20. // onSaveInstanceState(). We restore some state in onCreate(), while we can optionally restore
  21. // other state here, possibly usable after onStart() has completed.
  22. // The savedInstanceState Bundle is same as the one used in onCreate().
  23. @Override
  24. public void onRestoreInstanceState(Bundle savedInstanceState) {
  25. textView.setText(savedInstanceState.getString(TEXT_VIEW_KEY));
  26. }
  27. // invoked when the activity may be temporarily destroyed, save the instance state here
  28. @Override
  29. public void onSaveInstanceState(Bundle outState) {
  30. outState.putString(GAME_STATE_KEY, gameState);
  31. outState.putString(TEXT_VIEW_KEY, textView.getText());
  32. // call superclass to save any view hierarchy
  33. super.onSaveInstanceState(outState);
  34. }

可以看到重写的onSaveInstanceState()方法中存入了游戏状态textView的文字,在onRestoreInstanceState()方法中,调用了获取当前文字并设置的方法,并且我们可以在这个例子中看到onCreate()方法中是如何利用savedInstanceState这个对象的——不为空那么就获取数据

  1. if (savedInstanceState != null) {
  2. gameState = savedInstanceState.getString(GAME_STATE_KEY);
  3. }

3、onStart()

当 Activity 进入“onStart”状态时,系统会调用onStart()方法。onStart() 调用使 Activity 对用户可见,也就是在这个方法中,我们可以看到app的前端activity展示了

onStart() 方法会非常快速地完成,并且与onCreate()一样,Activity 不会一直处于“onStart”状态。一旦此回调结束,Activity 便会进入“onResume”状态,系统将调用 onResume() 方法。

4、onResume()

onResume是应用与用户互动的状态,也就是具有焦点,我们可以对app中的各种组件进行操作的一个焦点状态,这个时候是用户与应用的交互的状态。

5、onPause()

onPause状态是用户对这个activity失去焦点,但是onPause这个状态,用户还是对activity可见的。

举个例子,有两个activity,第一个activity A,第二个activity B。

如果A使用透明主题,B使用默认主题。当由A通过Intent跳转到B时,会失去A的焦点,调用onPause()方法,但是,因为时透明主题,所以我们在看B的同时,可以看到A,也就是A仍然是可见的,所以A不会调用onStop(),也就是不会被停止

如果这个时候我们点击back按钮,从B返回到了A,A会重新调用onResume()方法,因为A得到了焦点,但是并不会调用onStart(),因为我们的A从来没有被停止过,仍然有可见的界面

6、onStop()

onStop状态就是我们对这个activity失去了焦点,但是它并未被销毁

举一个常见的例子——微信扫一扫,我们从微信主页打开微信扫一扫,主页失去了焦点并且不可见,成为了onStop的状态,返回之后主页又得到了焦点,执行了onStart()onResume()

7、onDestroy()

onDestroy被执行,调用此回调的原因如下:

  1. Activity 即将结束(由于用户彻底关闭Activity或由于系统为Activity调用finish()方法
  2. 由于配置变更(例如设备旋转多窗口模式),系统暂时销毁Activit

如果Activity即将结束,onDestroy()是 Activity 收到的最后一个生命周期回调。如果由于配置变更而调用 onDestroy(),系统会立即新建 Activity 实例,然后在新配置中为新实例调用onCreate()

8、横竖屏的影响

在理解了各个部分的生命周期之后,我们应该注意到,在APP中横竖屏的切换,会导致生命周期改变——先销毁、再创建一个新的。

那么我们可能遇到这样的情况——我们竖屏看电影的时候,进度条在20分钟,但是如果我们切换成了横屏进度条就从头开始了。这种APP出现的问题就是没有处理横竖屏切换带来的影响。

之所以会出现上述情况,是因为activity的一个生命周期已经结束了,横屏进入了一个新的生命周期。

解决方法有两种:

  • 在activity中设置android:screenOrientation="landscape",这样APP始终保持在横屏。
  • 在activity中设置android:configChanges="keyboardHidden|screenSize|orientation",这样activity在“键盘隐藏”、“屏幕大小变化”、“横竖屏切换”的时候,不会产生影响。

一般游戏开发使用第一种方法,因为游戏需要一直横屏。电影播放等使用第二种方法,这样就可以保持横竖屏进度条一致啦!

后话

关于Android中的activity中生命周期的理解到此结束了,之后还有对activity的启动模式的分析!

建议搭配安卓开发文档进行观看,文章内容仅供参考!

【Android】安卓四大组件之Activity(二)的更多相关文章

  1. 【Android】安卓四大组件之Activity(一)

    [Android]安卓四大组件之Activity(一) 前言 Activity是Android学习中的一个重要组件,想要对其进行系统的了解可以分为几块内容,这一大章节的内容是有关于activity之间 ...

  2. Android的四大组件之Activity

    Android的四大组件之Activity Activity:是Android组件中最基本也是最为常见用的四大组件(Activity,Service服务,Content Provider内容提供者,B ...

  3. 安卓四大组件之一activity

    概要说明 Activity是Android组件中最基本也是最为常见用的四大组件(Activity,Service服务,Content Provider内容提供者,BroadcastReceiver广播 ...

  4. 从零开始学android开发-四大组件之一 Activity

    1.Activity是Android四大组件(Application Components)之一,简单来说Activity就是平常所见到的用户界面,一般情况下,一个Activity所占的窗口是满屏的, ...

  5. 安卓四大组件之activity和获取网络资源之断点续传

    Day05 数据存储及多线程断点续传1.数据提交到服务器两种方式的优缺点* GET请求优点:使用非常方便,只需要在url后面组拼数据.缺点:数据在url的后面组拼,不安全.有数据长度限制.* POST ...

  6. android中四大组件之间相互通信

    好久没有写有关android有关的博客了,今天主要来谈一谈android中四大组件.首先,接触android的人,都应该知道android中有四大组件,activity,service,broadca ...

  7. Android的四大组件

    Android的四大组件:Activity.Service.BroadcastReceiver.Content Provider. Content Provider 属于Android应用程序的组件之 ...

  8. Android四大组件之Activity(活动)及其布局的创建与加载布局

    Android四大组件之Activity(活动)及其布局的创建与加载布局 什么是Activity ? 活动(Activity)是包含用户界面的组件,主要用于和用户进行交互的,一个应用程序中可以包含零个 ...

  9. Android深入四大组件(四)Android8.0 根Activity启动过程(前篇)

    前言 在几个月前我写了Android深入四大组件(一)应用程序启动过程(前篇)和Android深入四大组件(一)应用程序启动过程(后篇)这两篇文章,它们都是基于Android 7.0,当我开始阅读An ...

随机推荐

  1. Linux执行脚本报错:-bash: ./xx.sh: /bin/bash^M: bad interpreter: No such file or directory

    1.用vim打开文本 输入 : set ff 这里要先按":"号 显示文件为dos格式 2.强制装换格式为unix 先按冒号":" set ff=unix 然后 ...

  2. 【LeetCode】744. Find Smallest Letter Greater Than Target 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 线性扫描 二分查找 日期 题目地址:https:// ...

  3. 【LeetCode】392. Is Subsequence 解题报告(Python)

    [LeetCode]392. Is Subsequence 解题报告(Python) 标签: LeetCode 题目地址:https://leetcode.com/problems/is-subseq ...

  4. 【LeetCode】416. Partition Equal Subset Sum 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 DFS 动态规划 日期 题目地址:https://l ...

  5. 1421 最大MOD值

    1421 最大MOD值 基准时间限制:1 秒 空间限制:131072 KB  有一个a数组,里面有n个整数.现在要从中找到两个数字(可以是同一个) ai,aj ,使得 ai mod aj 最大并且 a ...

  6. Docker 与 K8S学习笔记(七)—— 容器的网络

    本节我们来看看Docker网络,我们这里主要讨论单机docker上的网络.当docker安装后,会自动在服务器中创建三种网络:none.host和bridge,接下来我们分别了解下这三种网络: $ s ...

  7. @Transactional 注解实现

    @Transactional注解简介 @Transactional是spring中声明式事务管理的注解配置方式,相信这个注解的作用大家都很清楚.@Transactional注解可以帮助我们把事务开启. ...

  8. CS5266参数|Capstone CS5266|CS5266应用方案

    随着目前手机.笔电和平板类产品都是用的Type-C接口,特别是苹果类的笔电和平板就只有一个Type-C接口,在很多工作.学习.娱乐中突显很多不方便的情况,别是需要一些其他的功能如:鼠标键盘接口USB2 ...

  9. Vue.js高效前端开发 • 【Vue基本指令】

    全部章节 >>>> 文章目录 一.Vue模板语法 1.插值 2.表达式 3.指令概述 4.实践练习 二.Vue绑定类样式和内联样式 1.Vue绑定类样式 2.Vue绑定内联样式 ...

  10. Java初学者作业——编写Java程序,在控制台中输入一个数字,要求定义方法实现找出能够整除该数字的所有数字。

    返回本章节 返回作业目录 需求说明: 编写Java程序,在控制台中输入一个数字,要求定义方法实现找出能够整除该数字的所有数字. 实现思路: 定义方法findNums(),用于实现查找所有能够整除指定数 ...