开启Android学习之旅-3-Android Activity

Android Activity

本文总结《第一行代码 Android》第3版的内容

环境:
Android Studio Giraffe | 2022.3.1 Patch 3

Activity 是什么?

Activity 简单将就是UI界面,包含两部分 Activity 类 和应用布局文件,如果是 Compose 则另说,一般入门Android,都是从Activity开始的。
我们写一个程序,常常找应用启动入口,像 java 的 main()函数,那么 Activity 的应用入口在哪?下面通过创建项目认识。
在创建 Android 项目时,要选择 No Activity,是因为 Android Studio 2022 中如果选择 Empty Activity,会默认使用 Compose UI。在创建完成后,手动添加“Empty Activity”:
在这里插入图片描述
如果勾选 Launcher Activity,那么该 Activity 一般就是应用启动的时候,首先显示的。在这里插入图片描述
在创建 Activity 之后,会自动在 AndroidManifest 注册 Activity:
应用入口在 AndroidManifest.xml 中一般会有标识:

<activityandroid:name=".FirstActivity"android:launchMode="singleTask"android:exported="true"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity>

Acttivity 的基本用法

在Android Studio 添加 Activity 之后,会创建两个文件:一个类,一个xml文件。类用来写逻辑,xml写UI布局。
修改 xml 布局,使用LinearLayout,默认的太复杂,添加 Button 控件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".FirstActivity"><Buttonandroid:id="@+id/button1"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="Button 1"/>
</LinearLayout>

然后在 Activity中添加逻辑:

// button 点击事件
button1.setOnClickListener{Toast.makeText(this,"你点击了按钮",Toast.LENGTH_SHORT).show()

一个最简单的应用就完成了。

使用 Toast 消息提示

Toast 用于提示用户,用法如上面,第三个参数有两种 Toast.LENGTH_SHORT 和 Toast.LENGTH_LONG,显示时长不一样。

Activity 界面添加 Menu

步骤1: 添加 Menu 资源文件
在这里插入图片描述

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"><itemandroid:id="@+id/add_item"android:title="添加"/><itemandroid:id="@+id/remove_item"android:title="删除"/>
</menu>

步骤二:在 Activity中 重写 onCreateOptionsMenu() 方法

override fun onOptionsItemSelected(item: MenuItem): Boolean {when(item.itemId){R.id.add_item -> Toast.makeText(this,"添加菜单项",Toast.LENGTH_SHORT).show()R.id.remove_item -> Toast.makeText(this,"删除菜单项",Toast.LENGTH_SHORT).show()}return true}

效果:
在这里插入图片描述

销毁Activity

在按返回键时,Activity 可以被销毁,在代码中使用 finish() 方法

不同 Activity 中跳转

首先理解什么是 Intent?
在Android中,Intent是一种消息传递机制,用于在组件之间进行通信,如启动活动、启动服务、传递数据等。根据其使用方式,Intent可以分为显式Intent和隐式Intent。

显式Intent:显式Intent是指明确指定要启动的组件(如Activity、Service等)的名称。这种Intent通常用于应用内部的组件间通信。例如,从一个Activity启动另一个Activity。

val intent = Intent(this, SecondActivity::class.java)
startActivity(intent)

在上述代码中,我们明确指定了要启动的Activity是SecondActivity,因此这是一个显式Intent。

FirstActivity 跳转到 SecondActivity 使用 显式 Intent。

隐式Intent:隐式Intent并没有明确指定要启动的组件,而是指定了一种动作(Action)和数据(Data),然后由系统解析这个Intent,找到合适的组件来处理这个Intent。这种Intent通常用于启动其他应用的组件。例如,打开网页、拨打电话等。

val intent = Intent(Intent.ACTION_VIEW)
intent.data = Uri.parse("https://www.baidu.com")
startActivity(intent)

在上述代码中,我们指定了一个动作ACTION_VIEW和一个数据https://www.baidu.com,系统会找到能处理这个动作和数据的应用(如浏览器)来启动。因此这是一个隐式Intent。
如果让我们的程序能够响应隐式Intent,需要在 AndroidManifest.xml 中注册:

<activityandroid:name=".ThirdActivity"android:exported="true" ><intent-filter tools:ignore="AppLinkUrlError"><action android:name="android.intent.action.VIEW"/><category android:name="android.intent.category.DEFAULT"/><data android:scheme="https"/></intent-filter></activity>

调用方法:

 // 隐式Intentval intent = Intent("com.alex.activitytest.ACTION_START")intent.addCategory("com.alex.activitytest.MY_CATEGORY")startActivity(intent)

不同Activity传递数据

FirstActivty 启动 SecondActivity 并传递数据:

  // 启动Activity并传递数据val data="Hello SecondActivity"val intent = Intent(this,SecondActivity::class.java)intent.putExtra("extra_data",data)startActivity(intent)

SecondActivity 接收数据:在 onCreate方法中

val extraData=intent.getStringExtra("extra_data")
Toast.makeText(this,extraData,Toast.LENGTH_SHORT).show()

如果 SecondActivity 需要向 FirstActivty 返回数据,需要三步,在 FirstActivty 调用的时候:把 startActivity(intent) 替换为

startActivityForResult(intent,1)

SecondActivity 返回数据:

val intent = Intent()
intent.putExtra("data_return","Hello, FirstActivity")
setResult(RESULT_OK,intent)
// 销毁当前Activity
finish()

FirstActivty 接收数据:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {super.onActivityResult(requestCode, resultCode, data)when (requestCode) {1 -> if (resultCode == RESULT_OK) {val returnedData = data?.getStringExtra("data_return")Log.d("FirstActivity", "returned data is $returnedData")}}
}

startActivityForResult 与 onActivityResult 被废弃了,可以参考这篇文章进行更新:

startActivityForResult被标记为废弃?Activity Result API闪亮登场!

Activity 生命周期

Android 使用 task 来管理 Activity,一个任务就是一组存放在返回栈里的 Activity的集合。启动Activity,Activity入栈,Activity销毁就会出栈。显示的Activity总是在栈顶。
在这里插入图片描述

Activity 的四种状态

  • 运行状态
    Activity处于栈顶
  • 暂停状态
    比如一个Activity上弹出一个对话框,此时Activity处于暂停状态
  • 停止状态
    Activity 不处于栈顶,并且完全不可见
  • 销毁状态
    Activity 从返回栈中移除

Activity 生命周期

  • onCreate()。会在Activity第一次被创建的时候调用。应该在这个方法中完成Activity的初始化操作,比如加载布局、绑定事件等。
  • onStart()。这个方法在Activity由不可见变为可见的时候调用。
  • onResume()。这个方法在Activity准备好和用户进行交互的时候调用。此时的Activity一定位于返回栈的栈顶,并且处于运行状态。
  • onPause()。这个方法在系统准备去启动或者恢复另一个Activity的时候调用。我们通常会在这个方法中将一些消耗CPU的资源释放掉,以及保存一些关键数据,但这个方法的执行速度一定要快,不然会影响到新的栈顶Activity的使用。
  • onStop()。这个方法在Activity完全不可见的时候调用。它和onPause()方法的主要区别在于,如果启动的新Activity是一个对话框式的Activity,那么onPause()方法会得到执行,而onStop()方法并不会执行。
  • onDestroy()。这个方法在Activity被销毁之前调用,之后Activity的状态将变为销毁状态。
  • onRestart()。这个方法在Activity由停止状态变为运行状态之前调用,也就是Activity被重新启动了。

在这里插入图片描述
结合GPT,谈谈应用场景:
onCreate():
应用场景: 初始化 Activity,设置布局,初始化成员变量和数据绑定。
例子: 在一个音乐播放器应用中,在 onCreate() 中加载布局,初始化播放控制按钮和音轨信息。

onStart():
应用场景: 让 Activity 对用户可见,进行一些轻量级的资源初始化或恢复操作。
例子: 在新闻应用中,当 Activity 变为可见时,可以在 onStart() 中开始加载新闻列表。

onResume():
应用场景: 当 Activity 与用户交互前,恢复暂停的动画,初始化相机等。
例子: 在相机应用中,在 onResume() 方法中打开相机预览。

onPause():
应用场景: 暂停或调整不再需要的操作,如暂停动画,释放相机资源。
例子: 如果用户在编辑照片的应用中接到电话,onPause() 可用于暂停编辑进度或保存状态。

onStop():
应用场景: 当 Activity 不再可见时,释放或调整资源和操作,如停止播放媒体,取消网络请求。
例子: 在视频播放应用中,当用户离开播放界面,可以在 onStop() 中停止视频播放并释放播放器资源。

onDestroy():
应用场景: 清理资源,如关闭数据库连接,注销广播接收器。
例子: 在社交应用中,当 Activity 销毁时,关闭数据库连接和注销监听网络变化的广播接收器。

onRestart():
应用场景: 在 Activity 从停止状态回到活动状态时调用,用于重新初始化在 onStop() 中释放的资源。
例子: 在购物应用中,如果用户从购物车界面切换到其他应用然后返回,可以在 onRestart() 中刷新购物车数据。

如果从网络请求新闻列表数据,可以写在 onStart 或 onResume 方法中。如果你希望每次 Activity 变得可见时都刷新数据,那么 onStart() 是合适的地方。如果你希望在 Activity 每次回到用户交互前台时刷新数据,则 onResume() 更为合适。此外,考虑到网络请求可能会耗时并影响用户体验,推荐使用异步处理(如使用 AsyncTask 或 Retrofit 等网络库)来进行网络请求,避免阻塞主线程。

Activity 保存状态数据

如果 Activity 在停止状态时,有可能被回收,再返回时,如果没有数据,Activity可能无法正常显示,此时需要保存状态,可以使用 onSaveInstanceState方法,确保在回收前保存

override fun onSaveInstanceState(outState: Bundle) {super.onSaveInstanceState(outState)val tempData = "Something you just typed"outState.putString("data_key", tempData)
}

在onCreate() 恢复数据:

override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)Log.d(tag, "onCreate")setContentView(R.layout.activity_main)if (savedInstanceState != null) {val tempData = savedInstanceState.getString("data_key")Log.d(tag, "tempData is $tempData")}...
}

Activity 四种启动模式

Android 中Activity的四种启动模式及使用场景如下:

  1. Standard

用途: 每次启动 Activity 时都会创建一个新的实例,无论该 Activity 是否已经存在于任务栈中。

应用场景: 这是默认模式。适用于大多数标准的 Activity,如显示列表项的详细信息。例如,在邮件应用中,用户点击一个邮件时,每次都会创建一个新的邮件详情 Activity,即使是同一个邮件。

在这里插入图片描述
2. SingleTop

用途: 如果新的 Activity 已经是任务栈的顶端,则不会创建新的实例,而是复用栈顶的实例,并通过 onNewIntent() 方法接收新的 Intent。

应用场景: 适用于需要接收新信息且频繁启动但不需要多实例的 Activity。例如,在聊天应用中,如果用户已经在聊天界面,新消息的通知点击后只更新当前的聊天界面,而不重新创建 Activity。
在这里插入图片描述

  1. SingleTask

用途: 只创建一个实例,该实例会在新的任务栈中。如果 Activity 已经存在,则把这个 Activity 之上的所有其他 Activity 出栈,使这个 Activity 显示在最前。

应用场景: 适用于作为应用中单一入口的 Activity,如主页。例如,在浏览器应用中,主页 Activity 设置为 singleTask,无论从哪里启动,都只有一个主页实例。
在这里插入图片描述
4. SingleInstance

用途: 类似于 singleTask,但系统会为这种 Activity 创建一个新的任务栈,并且在这个栈中只有这个 Activity 实例。

应用场景: 适用于需要与应用完全分离的模块,例如,一个应用内的浮动小窗口或者是需要与其他应用共享的 Activity。例如,一款具有浮动小窗功能的音乐播放器,其播放控制界面可以设置为 singleInstance 模式。
举例:

Activity最佳实践

通过BaseActivity知晓当前在哪一个Activity

open class BaseActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)Log.d("BaseActivity", javaClass.simpleName)}
}

全局管理Activity,随时退出程序

新建单例类ActivityCollector

package com.alex.activitytest
import android.app.Activity/*** @Author      : alex* @Date        : on 2023/12/28 15:59.* @Description :描述*/
object ActivityCollector {private val activities = ArrayList<Activity>()fun addActivity(activity: Activity){activities.add(activity)}fun removeActivity(activity: Activity){activities.remove(activity)}fun finishAll(){for(activity in activities){if(!activity.isFinishing){activity.finish()}}activities.clear()}
}

这个方法在测试的时候不行,比如点击按钮执行 ActivityCollector.finishAll(), 系统会重启App,即时加了下面的代码也一样。

android.os.Process.killProcess(android.os.Process.myPid())

可参考:https://blog.csdn.net/shulianghan/article/details/116402759

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[NSSRound#3 Team]This1sMysql

[NSSRound#3 Team]This1sMysql 源码 <?php show_source(__FILE__); include("class.php"); $conn new mysqli();if(isset($_POST[config]) && is_array($_POST[config])){foreach($_POST[config] as $key > $val){$value is_numeric($var)?(int)$…

几种常见的CSS三栏布局?介绍下粘性布局(sticky)?自适应布局?左边宽度固定,右边自适应?两种以上方式实现已知或者未知宽度的垂直水平居中?

几种常见的CSS三栏布局 流体布局 效果&#xff1a; 参考代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1…

【致远FAQ】V8.0_甘特图能不能实现行表头一级一级显示(树形结构)

问题描述 甘特图能不能实现行表头一级一级显示&#xff08;树形结构&#xff09; 问题解决 设置统计时把合并同类型和显示行合计都勾选上就可以了 效果参考

Python爬虫实战之萝卜投研

Python爬虫实战之萝卜投研 声明&#xff1a;以下内容均为我个人的理解&#xff0c;如果发现错误或者疑问可以联系我共同探讨 爬虫介绍 网站介绍 本次要爬取的网站为*萝卜投研*&#xff0c;是利用人工智能、大数据、移动应用技术,建立的股票基本面分析智能投研平台&#xff…

MongoDB入门介绍与实战

目录 1. 什么是MongoDB&#xff1f; 2. 安装MongoDB 1. 离线安装 2. 使用docker-compose安装 3. mongo命令行实战 1. 连接到 MongoDB 数据库 2. 创建集合&#xff08;表&#xff09; 3. 插入数据 4. 查询数据 5. 更新数据 6. 删除数据 4. Springboot集成MongoDB实战…

Java经典框架之Dubbo

Dubbo Java 是第一大编程语言和开发平台。它有助于企业降低成本、缩短开发周期、推动创新以及改善应用服务。如今全球有数百万开发人员运行着超过 51 亿个 Java 虚拟机&#xff0c;Java 仍是企业和开发人员的首选开发平台。 课程内容的介绍 1. Dubbo概述 2. Dubbo基本应用 3…

FFmpeg安装保姆级教程

在上一篇文章《IOS&#xff1a;Safari无法播放MP4&#xff08;H.264编码&#xff09;》里我们使用了FFmpeg来设置MP4的Profile和Level值&#xff0c;从而转换出适合IOS Safari上播放的MP4文件。本文接着介绍一下FFmpeg的安装&#xff1a; 一、安装过程 &#xff08;1&#xf…

听GPT 讲Rust源代码--compiler(16)

File: rust/compiler/rustc_span/src/lib.rs 在Rust源代码中&#xff0c;rust/compiler/rustc_span/src/lib.rs文件定义了与Rust编译器源代码位置相关的数据结构和功能。 下面是对一些重要结构和枚举类型的详细介绍&#xff1a; SessionGlobals: 代表编译器会话&#xff08;Ses…

AWTK 开源串口屏开发(5) - MCU端 SDK 用法

AWTK 开源智能串口屏&#xff0c;不但开放了串口屏端全部源码&#xff0c;还提供了MCU 端 SDK&#xff0c;大大加快 MCU 软件的开发。本介绍一下 MCU 端 SDK 在不同平台上的用法。 完整示例可以参考下面的几个例子&#xff1a; 普通嵌入式系统 mcu/stm32/hmi_app/hmi_app.c 低…

位移贴图还原电影3D角色

在线工具推荐&#xff1a; 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 位移贴图&#xff08;Displacement Map&#xff09;在电影制作中是一…

老师们居然这样把期末考试成绩发给家长——群发成绩系统的妙用

在现代社会&#xff0c;随着科技的发展和教育的进步&#xff0c;家校之间的沟通方式也在不断更新和完善。其中&#xff0c;群发成绩系统作为一种新型的教育信息化工具&#xff0c;在期末考试成绩的传递方面发挥了重要作用。老师们通过群发成绩系统&#xff0c;将期末考试成绩快…

Linux下Redis6下载、安装和配置教程-2024年1月5日

Linux下Redis6下载、安装和配置教程-2024年1月5日 一、下载二、安装三、启动四、设置开机自启五、Redis的客户端1.Redis命令行客户端2.windows上的图形化桌面客户端 一、下载 1.Redis的官方下载&#xff1a;https://redis.io/download/ 2.网盘下载&#xff1a; 链接&#xff…