【安卓基础3】Activity(一)
🏆作者简介:|康有为| ,大四在读,目前在小米安卓实习,毕业入职
🏆本文收录于 安卓学习大全,欢迎关注
🏆安卓学习资料推荐:
视频:b站搜动脑学院 视频链接 (他们的视频后面一部分没再更新,看看前面也挺好的)
书籍:《第一行代码》(第3版) by 郭霖 (z-lib.org)
思维导图: https://www.processon.com/view/link/62427cb2e0b34d0730e20e00(来自动脑学院)
目录
一、Activity入门
Activity的创建
1. 在layout目录下创建XML文件
2. 创建与XML文件对应的Java代码
3. 在AndroidManifest.xml中注册页面配置
Activity的跳转
Activity快捷创建
二、Activity的基本用法
在Activity中使用Toast
三、Activity的启动和结束
四、Activity的生命周期
分析Activity生命周期
将上文的细节提炼
状态之间的切换过程
Activity A 启动一个透明的 Activity B
异常情况下的生命周期
常见异常情况
1.资源相关的系统配置发生改变导致Activity被杀死并重新创建
2.系统内存不足导致低优先级的Activity被杀死
一、Activity入门
Activity可以理解为程序的一个界面或一个屏幕。
在Android中,Activity 是一个用于展示用户界面和处理用户交互的基本组件。它代表了用户与应用程序之间的单一屏幕,用户在应用程序中进行的每个操作通常都与一个 Activity 相关联。在Android应用程序中,通常会包含多个活动,每个活动都代表应用程序的一个界面或一个屏幕
先用Androidstudio创建一个Empty Views Activity 的 HelloWorld程序,java语言的
Activity的创建
完整的页面创建过程包括三个步骤,也就是创建下面的三个文件
1. 在layout目录下创建XML文件
创建成功后,添加下面代码
并在res/values/strings.xml文件 中添加文字
<resources><string name="app_name">HelloWorld-Java</string><string name="text2">文字2222222</string>
</resources>
2. 创建与XML文件对应的Java代码
写代码:
1.继承AppCompatActivity
2.重写onCreate方法(写onCreate会有提示,自动补全)
重写时选择这个protect修饰的这个onCreate方法
3.写上:setContentView(R.layout.activity_main2);
package com.example.helloworld_java;import android.os.Bundle;import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;public class MainActivity2 extends AppCompatActivity {@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main2);}
}
3. 在AndroidManifest.xml中注册页面配置
在这里加入一行代码,将这个activity注册到清单文件
<activity android:name=".MainActivity2"/>
因为MainActivity2 不是主activity,所以不用再修改 intent-filter的代码。
至此就创建好了 Activity2
Activity的跳转
我们想显示Activity2,就需要从主Activity中跳转到2,所以写一个按钮,加上点击跳转的事件,跳转到2。
在主Activity中加上按钮
<Buttonandroid:id="@+id/button"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="跳转" />
编写跳转事件(要写到主Activity中的onCreate方法里面,从主Activity 跳转到 其他Activity)
Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Intent intent = new Intent();intent.setClass(MainActivity.this,MainActivity2.class);startActivity(intent);}
});
效果
Activity快捷创建
直接在java文件包那里快捷创建
这样layout里面也会自动帮我们创建好文件
清单文件中也会自动帮我们注册好
快捷创建的layout中的xml文件,根是androidx.constraintlayout.widget.ConstraintLayout ,我们可以换成LinearLayout 。
androidx.constraintlayout.widget.ConstraintLayout 和 LinearLayout 是 Android 开发中常用的两种布局管理器,它们在布局设计和子视图排列方面有一些不同之处。
二、Activity的基本用法
在Activity中使用Toast
Toast是Android系统提供的一种非常好的提醒方式,在程序中可以使用它将一些短小的信息通 知给用户,这些信息会在一段时间后自动消失,并且不会占用任何屏幕空间。
在Android中,Toast 是一种简单的通知方式,可以在屏幕底部显示一小段时间的消息。以下是在 Activity 中使用 Toast 的基本步骤:
- 创建 Toast 对象: 使用 Toast.makeText() 方法创建一个 Toast 对象。
- 设置显示文本: 使用 setText() 方法设置要显示的文本内容。
- 设置时长: 使用 setDuration() 方法设置 Toast 的显示时长,可以选择 Toast.LENGTH_SHORT(短时,大约2秒)或 Toast.LENGTH_LONG(长时,大约3.5秒)。
- 显示 Toast: 调用 show() 方法显示 Toast。
以下是一个简单的示例:
import android.os.Bundle;
import android.view.Gravity;
import android.widget.Toast;import androidx.appcompat.app.AppCompatActivity;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 创建一个Toast对象Toast toast = Toast.makeText(this, "Hello, this is a Toast!", Toast.LENGTH_SHORT);// 设置Toast的显示位置(可选)toast.setGravity(Gravity.CENTER, 0, 0);// 显示Toasttoast.show();}
}
效果:
三、Activity的启动和结束
从当前页面跳到新页面,跳转代码如下:
startActivity(new Intent(源页面.this,目标页面.class));
从A -- 》 B ,那么B就是启动了
从当前页面回到上一个页面,相当于关闭当前页面,返回代码如下:
finish();//结束当前的活动页面
B结束之后,就返回到了A
示例
从A跳到B的java代码,xml里面写个按钮就行。
从B跳回A,也就是直接执行 finish 就行
四、Activity的生命周期
分析Activity生命周期
什么是 生命周期,就是从生到死的过程。
正常情况下,新建一个Activity A会顺序经历如下几个生命周期:
- onCreate:A正在被创建,这个方法中,我们可以做一些Activity的初始化操作。例如布局文件的加载与事件的绑定(setContentView,findViewById,setOnClickListener等)。
- onStart: A 正在被启动,A 由不可见变为可见时调用,此时 A 还无法与用户交互。此时可以做一些数据的初始化操作(开启线程去拉本地数据库数据,或从后台拉数据)。
- onResume: A 已经可见,并出现在前台,该Activity位于返回栈栈顶,可以响应用户的操作,即可以与用户交互了。
如果此时用户拉起另一个Activity B, Activity A会顺序经历如下几个生命周期:
4. onPause: 表示 A 正在停止,准备从前台返回至后台,此时可以做一些停止动画,数据存储等工作。值得注意的是,在onPause生命周期进行的工作不能太耗时,不然会影响 B 的显示。(Activity A的onPause执行完后,Activity B的onResume才会执行)。
5. onStop: 在 A 完全不可见时调用,紧随着onPause执行,表 A 即将停止,此时 A 已经不在前台,可以做一些稍微重量级的回收工作,但同样不能太耗时,(如果此时新打开的Activity B是对话框式的Activity,背景存在一定区域是透明的,则Activity A的onStop不会调用)。
6. onDestroy:表示 A 即将被销毁,在这里可以进行资源的回收、释放工作。一般是经过用户按下back键或者系统资源紧张时,将Activity A释放掉以获得更多的内存时调用。
Activity B经历了onResume生命周期后已经显示在前台,如果此时按下back返回键,从 B 页面返回,而 A 还停留在onStop,没有经过onDestroy生命周期的话,A 会经历如下几个生命周期后重新显示:
7. onRestart: A 由onStop停止状态,转为运行状态时调用,表 A 正在被重新启动。
8. onStart
9. onResume
可以看到,排除Activity退到后台的情况,Activity从创建到销毁,总共会经过6个生命周期,分别是onCreate,onStart,onResume,onPause,onStop,onDestroy。
通过上面的文字描述,看这个图应该已经很清楚了,不过,未提到的是,上图中onPause()还有个箭头指向了onResume(),这是一种极端情况。即考虑当Activity A 跳转到Activity B 的情况,此时 A 还在执行onPause() , B 还未显示出来。快速地从B回到A,此时会直接执行 A 的onResume()而不会走onRestart()。不过一般很难复现这种操作,大家留个心眼就行。
将上文的细节提炼
- onStart、onResume、onPause、onStop看起来回调调用的时机差不多,它们俩区别在哪呢?
onStart和onStop是从Activity是否可见的角度来回调的,而onResume和onPause则是从Activity是否位于前台、是否可以与用户交互的角度来回调的,除了这方面的差别,在时机使用过程中,它们没有其他明显区别。
- 从Activity A 跳转到Activity B,是先执行 A 的onPause(),还是先执行 B 的onResume()呢?
这部分设计Activity跳转的源码,源码逻辑太深、太复杂就不先在基础篇讨论了,大家目前 先记住结论就好:A 的onPause()会先执行,然后才执行 B 的onResume(),这个细节也是面试中可能会问到的点。
- 在onPause中不能进行耗时的操作,否则会影响新Activity的显示,稍微重一点的操作可以放在onStop中,但依然不能太耗时。
状态之间的切换过程
打开新页面的方法调用顺序为:
onCreate→onStart→onResume
关闭旧页面的方法调用顺序为:
onPause→onStop→onDestroy
Activity A 启动一个透明的 Activity B
- 如果 Activity A 启动一个透明的 Activity B,会经历哪些生命周期呢?
这是面试容易遇到的一个问题,因为 B 页面透明, 所以跳转到 B 页面后,A 页面依然可见,因此就不会调用 Activity A 的 onStop 方法。
一般情况,A/B 均不是透明页面:
A 跳转 B 页面会经历的生命周期:A.onPause() -> B.onCreate() -> B.onStart() -> B.onResume() -> A.onStop。
从 B 页面返回 A 页面经历的生命周期:B.onPause() -> A.onRestart() -> A.onStart() -> A.onResume() -> B.onStop()。
B是透明页面的情况:
如果 B 是透明的,A 跳转到 B:A.onPause() -> B.onCreate() -> B.onStart() -> B.onResume()。
从 B 返回 A:B.onPause() -> A.onResume() -> B.onStop()
异常情况下的生命周期
考虑一种异常情况,Activity C 打开了Actvity D后,C进入了停止状态(调用了onStop()),此时系统内存不足,需要回收 C(调用C的onDestroy()) ,当用户从 D 返回到 C,C 会被重新创建(调用onCreate())。如果原来 C 里边有临时状态存储着,比如TextView中的文字。那么从 D 返回 C 时,C因为重新创建,如果TextView未指定ID,那它原来的文字就会消失,这一定程度影响了用户的体验。
因此为了优化用户体验,Activity提供了一个onSaveInstanceState()回调方法,这个方法可以保证异常情况下,在Activity被回收之前一定会被调用。
onSaveInstanceState()方法会携带一个bundle参数,我们可以通过bundle对象,存储一些简单的状态信息。
Activity重新创建后,系统会调用onRestoreInstanceState(),并把Activity销毁时onSaveInstanceState()方法所保存的Bundle对象作为参数同时传递给onRestoreInstanceState()和onCreate()。
你可以选择这两个方法中任意一个来恢复数据,二者的区别是:onRestoreInstanceState一旦被调用,其bundle对象一定是有值的,而onCreate在正常启动Activity的情况下bundle对象是无值的。
调用时机
onSaveInstanceState()在onStop()之前调用,onRestoreInstanceState()会在onStart()之后调用。
异常情况下,Activity数据的存储和恢复的生命过程都是一样的。
常见异常情况
常见的异常情况主要有以下两种:
1.资源相关的系统配置发生改变导致Activity被杀死并重新创建
首先说说什么是系统配置信息。
不同手机设备的分辨率不同,要将图片适配不同大小的手机屏幕,我们通常会在drawable-xhdpi,drawable-xxhdpi,drawable-xxxhdpi等目录中存放对应大小的图片Resource文件。
当App启动时,系统就会根据当前设备的屏幕情况去加载合适的Resource资源。同一台设备的横屏和竖屏时的屏幕大小也是不一样的,如果当前Activity处于竖屏状态,突然旋转至横屏,那么此时系统的屏幕配置发生了改变。
默认情况下,Activity会被销毁并重建。因为这种销毁是一种非用户主导的、异常的情况,Activity会调用onSaveInstanceState()方法后销毁,重建时会再调用onRestoreInstanceState()方法,即走一遍异常情况的生命周期。
如何避免这种因为系统配置更改而导致Activity重建的异常情况?
如果app在应用配置变更期间无需更新资源,我们可以在AndroidManifest.xml文件中相应的Activity声明,自行处理相关配置的变更,从而阻止系统重建Activity。
只需指定相关的configChanges属性。比如下面的例子,就阻止了当屏幕发生旋转时Activity的系统自动重建。
<activity android:name=".MainActivity"android:configChanges="orientation|screenSize" />
当configChanges中指定的配置发生变化时,系统会调用Activity的onConfigurationChanged()方法,如果有需要处理配置变更的话,可以在这个方法手动处理。一般我们在屏幕旋转时,希望Activity能保持原样,不重建就好了,所以空实现该方法即可。
当然,需要自行处理时,比如检查当前设备的方向,你可以这么写:
override fun onConfigurationChanged(newConfig: Configuration) {super.onConfigurationChanged(newConfig)// Checks the orientation of the screenif (newConfig.orientation === Configuration.ORIENTATION_LANDSCAPE) {Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show()} else if (newConfig.orientation === Configuration.ORIENTATION_PORTRAIT) {Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show()}
}
configChanges属性可以指定很多属性,如果你还想指定更多配置,不同配置间用"|"分隔,比如上面那样。
部分常用的configChanges配置项目如下:
2.系统内存不足导致低优先级的Activity被杀死
这种情况就是我们分析异常情况下的生命周期时举的例子。Activity C 跳转至Activity D,C 处于后台,当系统内存资源不足时,C的优先级较低,会被系统销毁以获得更多的内存,然后再从 D 回到 C ,C 会被重建,走一遍异常时的数据存储和恢复的生命过程。
Activity按照优先级从高到低,可以分为如下三中情况:
- 前台Activity,正在与用户交互的Activity,其优先级最高。
- 可见但非前台Activity,比如Activity中弹出了一个对话框,导致Activity可见但出于后台,无法与用户直接交互。
- 后台Activity,已经被暂停的Activity,比如执行了onStop,用户看不见,优先级最低。
当系统内存不足时,系统会按照上述优先级的顺序去杀死Activity所在的进程。并在后续通过onSaveInstanceState()和onRestoreInstanceState()去存储和恢复数据。
如果一个进程中没有四大组件在执行,那么这个进程将会很快被系统杀死,因此一些后台工作不适合脱离四大组件而单独运行在后台中。比较好的方法是将后台的工作放到Service服务中,从而保证进程有一定的优先级,就不会容易被系统杀死了。
相关文章:

【安卓基础3】Activity(一)
🏆作者简介:|康有为| ,大四在读,目前在小米安卓实习,毕业入职 🏆本文收录于 安卓学习大全,欢迎关注 🏆安卓学习资料推荐: 视频:b站搜动脑学院 视频链接 &…...

SpringBoot基于JWT的token做登录认证
背景 我们在基于Session做登录认证的时候,会有一些问题,因为Session存储到服务器端,然后通过客户端的Cookie进行匹配,如果正确,则通过认证,否则不通过认证。这在简单的系统中可以这么使用,并且…...

[ 2024春节 Flink打卡 ] -- Paimon
2024,游子未归乡。工作需要,flink coding。觉知此事要躬行,未休,特记 Flink 社区希望能够将 Flink 的 Streaming 实时计算能力和 Lakehouse 新架构优势进一步结合,推出新一代的 Streaming Lakehouse 技术,…...

计算机网络——14CDN
CDN 视频流化服务和CDN:上下文 视频流量:占据着互连网大部分的带宽 Netflix,YouTube:占据37%,16%的下行流量 挑战:规模性-如何服务~1B用户? 单个超级服务器无法提供服务(为什么&am…...

Docker技术仓库
数据卷 为什么用数据卷? 宿主机无法直接访问容器中的文件容器中的文件没有持久化,导致容器删除后,文件数据也随之消失容器之间也无法直接访问互相的文件 为解决这些问题,docker加入了数据卷机制,能很好解决上面问题…...

Kotlin学习 6
1.接口 interface Movable {var maxSpeed: Intvar wheels: Intfun move(movable: Movable): String}class Car(var name: String, override var wheels: Int 4, _maxSpeed: Int) : Movable {override var maxSpeed: Int _maxSpeedget() fieldset(value) {field value}overr…...

⭐北邮复试刷题LCR 052. 递增顺序搜索树__DFS (力扣119经典题变种挑战)
LCR 052. 递增顺序搜索树 给你一棵二叉搜索树,请 按中序遍历 将其重新排列为一棵递增顺序搜索树,使树中最左边的节点成为树的根节点,并且每个节点没有左子节点,只有一个右子节点。 示例 1: 输入:root [5,…...

获取discord上自己创建的服务器的服务器ID、频道ID以及discord的登录token(用于第三方登录)
在服务器图标上右键点击-》复制服务器ID 在频道上右键点击-》复制频道ID F12->手机模式-》application-》local storage-》填写过滤条件【token】 我开发的chatgpt网站: https://chat.xutongbao.top...

图纸透明加密:保护机械图纸安全的新方法
随着信息技术的不断发展,机械制造行业对于图纸安全的需求越来越高。机械图纸是企业的核心竞争力之一,泄露可能导致严重的商业损失和技术风险。为了解决这一问题,图纸透明加密成为了一种新的保护机械图纸安全的方法。本文将介绍图纸透明加密的…...

基于springboot + vue实现的前后端分离-酒店管理系统
项目介绍 基于springboot vue实现的酒店管理系统一共有酒店管理员和用户这两种角色。 管理员功能 登录:管理员可以通过登录功能进入系统,确保只有授权人员可以访问系统。用户管理:管理员可以添加、编辑和删除酒店的用户,包括前…...

79.SpringBoot的核心注解
一、SpringBoot的核心注解 SpringBootApplication注解:这个注解标识了一个SpringBoot工程,它实际上是另外三个注解的组合,这三个注解是:SpringBootConfiguration:这个注解实际就是一个Configuration,表示启…...

MATLAB 导出可编辑的eps格式图像
任务描述:部分期刊要求提交可编辑的eps格式图像,方便美工编辑对图像进行美化 我试了直接print或者在figure窗口导出,发现导出的文件放到Adobe AI中并不能编辑,经Google找到解决办法: %EPS exportgraphics(gcf,myVect…...

四问带你搞懂 I3C
大家都知道 I2C ,它的全称是 Inter Integrated Circuit ,那 I3C 又是什么? I3C 是 MIPI (Mobile Industry Processor Interface)移动产业处理器接口联盟推出的,全称是 Improved Inter Integrated Circuit &…...

fastjson解析自定义get方法导致空指针问题
背景 为了在日志中把出入参打印出来,以便验证链路和排查问题,在日志中将入参用fastjson格式化成字符串输出,结果遇到了NPE。 问题复现 示例代码 public static void main(String[] args) {OrganizationId orgId new OrganizationId();N…...

github新手用法详解
GitHub是一个非常强大的版本控制工具,它为程序员提供了一个便捷的方式来管理代码、协作开发和参与开源项目。但对于新手来说,可能会觉得GitHub的使用有些复杂。因此,本篇文章将详细介绍GitHub的基本用法,帮助新手快速上手并充分利…...

MAC电脑系统清理空间免费版软件CleanMyMac X2024
大家好,我是那个总是被苹果电脑“内存已满”提示搞得焦头烂额的专业博主。如果你也像我一样,在使用Mac时经常遭遇卡顿、慢吞吞的情况,那么今天的Mac清理空间妙招分享绝对适合你! CleanMyMac X全新版下载如下: https://wm.makedi…...

notepad++运行python闪一下就没啦
问题:Notepad直接快捷键运行Python代码,出现闪一下就没了 解决措施: ①点击菜单运行(Run) --> 运行(Run)弹出的对话框 ②把 cmd /k python "$(FULL_CURRENT_PATH)" & ECHO. & PAUSE & EXIT 粘贴进入这个对话框内 ③点击保存&a…...

基于springboot+vue的课程答疑系统(前后端分离)
博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战,欢迎高校老师\讲师\同行交流合作 主要内容:毕业设计(Javaweb项目|小程序|Pyt…...

【工具类】非 sudo 运行 docker
非 root 运行 docker 命令 sudo groupadd docker sudo usermod -aG docker $USER newgrp docker sudo chown root:docker /var/run/docker.sock sudo chown "$USER":"$USER" /home/"$USER"/.docker -R sudo chmod grwx "$HOME/.docker&quo…...

力扣49.字母异位词分组
题目描述: 49. 字母异位词分组 难度 中等 给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。 字母异位词 是由重新排列源单词的所有字母得到的一个新单词。 示例 1: 输入: strs ["eat", "tea"…...

git操作--->在远程删除了某个分支,但本地使用git branch -r的时候还是会显示某个分支存在是什么原因
💕又迷糊了哈哈,以为自己命令执行错了,结果可能是缓存的原因:💕 😂如果你发现使用 git branch -r 命令显示了一个远程没有的分支,这可能是由以下几个原因造成的:😂 缓存…...

合并Windows电脑的不同分区(不同的盘)的方法
本文介绍在Windows操作系统的电脑中,将磁盘上的不同分区(例如E盘与F盘)加以合并的方法。 最近,想着将新电脑的2个分区加以合并;如下图所示,希望将E盘与F盘合并为一个分区。本文就介绍一下实现这一需求的具体…...

web前端安全性——iframe安全问题
1、概念 iframe安全问题可称作界面劫持,像点击劫持、拖放劫持、触屏劫持。就是我们的点击,拖放,触屏操作被劫持了,而去操作了其它的透明隐藏的界面。 **原理是利用透明层iframe,使用了CSS中的opacity或z-index等属性,…...

从零开始学习Netty - 学习笔记 - NIO基础 - 网络编程: Selector
4.网络编程 4.1.非阻塞 VS 阻塞 在网络编程中,**阻塞(Blocking)和非阻塞(Non-blocking)**是两种不同的编程模型,描述了程序在进行网络通信时的行为方式。 阻塞(Blocking)࿱…...

useRef有什么用?
看一下官网定义 useRef是一个React Hook,它能帮助引用一个不需要渲染的值 这句话透露出一个信息,不需要渲染的值可以用useRef引用,那需要渲染的值用什么引用呢?当然是useState了,需要渲染的值指的就是状态嘛࿰…...

vue3中,ref()、reactive()、computed()、watch() 和 watchEffect()的区别
ref()、reactive()、computed()、watch() 和 watchEffect() 是 Vue 3 中常用的响应式处理函数,它们的主要区别如下: ref():ref() 函数用于将一个普通的 JavaScript 值转化为响应式对象。它返回一个具有 value 属性的对象,我们可以…...

Java基于SpringBoot的校园轻博客系统,附源码
博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇…...

webstorm光标变成方块解决办法_webstorm光标变粗不能换行
webstorms光标变了 键盘上的insert是切换的快捷键,敲insert就可以来回切换了...

从计网的角度讲明白什么是网关
网关(Gateway)又称网间连接器、协议转换器。网关在传输层上以实现网络互连,是最复杂的网络互连设备,仅用于两个高层协议不同的网络互连。网关的结构也和路由器类似,不同的是互连层。网关既可以用于广域网互连,也可以用于局域网互连…...

如何选择最适合的图纸加密软件?安秉网盾软件用户体验及性价比
安秉网盾图纸加密软件是一款功能强大的图纸加密工具,具有以下特点和优势: 全盘加密:安秉网盾采用先进的加密算法,能对文件、文件夹、磁盘等数据进行全面加密,确保数据在存储和传输过程中的安全性。 监控与审计&#x…...