【Android重点知识突破系列1】——Activity

一.Activity概念

移动应用体验与桌面体验的不同之处在于,用户与应用的互动并不总是在同一位置开始,而是经常以不确定的方式开始。例如,如果您从主屏幕打开电子邮件应用,可能会看到电子邮件列表,如果您通过社交媒体应用启动电子邮件应用,则可能会直接进入电子邮件应用的邮件撰写界面。

Activity 类的目的就是促进这种范式的实现。当一个应用调用另一个应用时,调用方应用会调用另一个应用中的 Activity,而不是整个应用。通过这种方式,Activity 充当了应用与用户互动的入口点。您可以将 Activity 实现为 Activity 类的子类。

Activity 提供窗口供应用在其中绘制界面。此窗口通常会填满屏幕,但也可能比屏幕小,并浮动在其他窗口上面。通常,一个 Activity 实现应用中的一个屏幕。例如,应用中的一个 Activity 实现“偏好设置”屏幕,而另一个 Activity 实现“选择照片”屏幕。

大多数应用包含多个屏幕,这意味着它们包含多个 Activity。通常,应用中的一个 Activity 会被指定为主 Activity,这是用户启动应用时出现的第一个屏幕。然后,每个 Activity 可以启动另一个 Activity,以执行不同的操作。例如,一个简单的电子邮件应用中的主 Activity 可能会提供显示电子邮件收件箱的屏幕。主 Activity 可能会从该屏幕启动其他 Activity,以提供执行写邮件和打开邮件这类任务的屏幕。

虽然应用中的各个 Activity 协同工作形成统一的用户体验,但每个 Activity 与其他 Activity 之间只存在松散的关联,应用内不同 Activity 之间的依赖关系通常很小。事实上,Activity 经常会启动属于其他应用的 Activity。例如,浏览器应用可能会启动社交媒体应用的“分享”Activity。

要在应用中使用 Activity,您必须在应用的清单中注册关于 Activity 的信息,并且必须适当地管理 Activity 的生命周期。本文的后续内容将介绍这些主题。

二.Activity生命周期

此处放一张图,无须再赘述什么。
在这里插入图片描述
当一个Actiivity新创建时,其生命周期如下:

当一个Activity关闭时,其生命周期如下:
在这里插入图片描述
当一个Activity退到后台时,其生命周期如下:
在这里插入图片描述

当一个Activity由后台回到前台时,其生命周期如下:
在这里插入图片描述
当横竖屏切换时,其生命周期如下:
在这里插入图片描述

三.启动模式

3.1 Activity四种启动模式

3.1.1 基本概念
  • standard

新建一个Activity就在页面栈中入栈一个Activity。

  • singleTop

如果当前Activity已经在栈顶,重复创建该Activity时不会新建,而是复用已有的在栈顶的Activity。如果当前Activity不在栈顶,则会新建实例。

  • singleTask

栈内只允许有唯一的Activity实例,再次重复新建时会把该Activity上方的其他Activity踢出栈GC掉,该Activity此时也就顶到了栈顶。

  • singleInstance

新起一个任务栈来存新的Activity实例。

3.1.2 taskAffinity属性

taskAffnity翻译为任务相关性,该参数标识了一个Activity所需要的任务的名字。在默认情况下,所有Activity所需的任务的名字都是应用的包名,但是我们可以为Activity单独设定所需栈的名字。taskAffnity属性不能设置为包名,否则相当于无效设定;taskAffnity只能和singleTask启动模式搭配使用,在其他情况下设置没有意义。

3.1.3 Intent中标志位设置启动模式

- FLAG_ACTIVITY_CLEAR_TOP

如果设置该属性,并且正在启动的Actvity已在当前任务中运行,那么与其启动该Activity的新实例,不如关闭该Activity之上的所有其他Activity,并将此Intent传递给将旧活动(现在顶部)作为新的Intent。

例如,考虑一个由以下Activity组成的任务:A,B,C,D。如果D调用具有解析为Activity B组件的Intent的startActivity(),则C和D将完成,并且B接收给定的Intent ,则堆栈现在为:A,B。

在上面的示例中,Activity B的当前正在运行的实例将通过onNewIntent()方法接收在此处开始的新Intent,或者自行finish并使用新Intent重新启动。如果已将其启动模式声明为默认,并且未将FLAG_ACTIVITY_SINGLE_TOP设置到同一Intent,则它将finish并重新创建;对于所有其他启动模式,或者如果设置了FLAG_ACTIVITY_SINGLE_TOP,则此Intent将被传递到当前实例的onNewIntent()。

此启动模式还可以与FLAG_ACTIVITY_NEW_TASK结合使用,以达到良好效果:如果用于启动任务的根Activity,它将把该任务的任何当前正在运行的实例置于前台,然后将其清除为根状态。例如,当从通知管理器启动活动时,此功能特别有用。

- FLAG_ACTIVITY_SINGLE_TOP

如果设置了该属性,则如果该Activity已经在任务顶运行,则不会启动该活动。类似于launchMode的singleTop。

  • FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

如果设置,则新Activity不保留在最近启动的Activity列表中。

- FLAG_ACTIVITY_NO_HISTORY

如果设置,则新Activity不会保留在历史记录堆栈中。 一旦用户离开它,Activity就结束了。 也可以使用noHistory属性设置。

如果设置,则在当前Activity开始一个新Activity(设置结果并完成)时,永远不会调用onActivityResult()。

- FLAG_ACTIVITY_NEW_TASK

如果设置,此Activity将成为此历史记录堆栈上新任务的开始。任务(从启动它的Activity到下一个任务Activity)定义了用户可以移动到的原子Activity组。任务可以移到前台和后台;特定任务内的所有Activity始终保持相同的顺序。

希望呈现“launcher”样式行为的Activity通常使用此标志:它们为用户提供了可以完成的单独操作的列表,否则,这些操作完全独立于启动它们的Activity而运行。

使用此标志时,如果你正在启动的Activity恰好正在任务中运行,那么将不会启动新的Activity;取而代之的是,当前任务将以其上次进入的状态简单地显示在前台。

当调用者从正在启动的Activity中请求结果时,不能使用此标志。

在Service中启动Activity时要加该属性,否则会报异常。

3.1.4 startActivity场景

在应用中打开新的Activity基本可以分为以下两种情况。

- 目标Activity就在本应用中

直接在Manifest的launchMode属性中灵活配置,任务栈也可以随意配置。

- 目标Activity在第三方应用中

要优先考虑新打开的Activity是和自己的App放在同一个任务栈中还是新起一个任务栈。然后再考虑Activity的启动模式,通过Intent.setFlags()来配置。

3.2 Activity四种启动模式的使用场景

- standard

不配置就是默认该模式

- singleTop

登录页面、WXEntryActivity、WXPayEntryActivity、推送通知栏页

- singleTask

支付页面、逻辑主页面、WebView页面、付款页面、确认订单页面

- singleInstance

系统launcher、锁屏页面、来电显示页面

3.3 Intent

Intent 是一个消息传递对象,消息大小是有限制的,不要接近或超过1M。可以用来从其他应用组件请求操作。尽管 Intent 可以通过多种方式促进组件之间的通信,但其基本用例主要包括以下三个:

- 启动 Activity

Activity 表示应用中的一个屏幕。通过将 Intent 传递给 startActivity(),可以启动新的 Activity 实例。Intent 用于描述要启动的 Activity,并携带任何必要的数据。

如果希望在 Activity 完成后收到结果,请调用 startActivityForResult()。在 Activity 的 onActivityResult() 回调中, Activity 将结果作为单独的 Intent 对象接收。

- 启动服务

Service 是一个不使用用户界面而在后台执行操作的组件。

对于 Android 5.0(API 级别 21)之前的版本,您可以使用 Service 类的方法来启动服务。通过将 Intent 传递给 startService(),可以启动服务执行一次性操作(例如,下载文件)。Intent 用于描述要启动的服务,并携带任何必要的数据。

如果服务旨在使用客户端-服务器接口,则通过将 Intent 传递给 bindService(),可以从其他组件绑定到此服务。

- 传递广播

广播是任何应用均可接收的消息。系统将针对系统事件(例如:系统启动或设备开始充电时)传递各种广播。通过将 Intent 传递给 sendBroadcast() 或 sendOrderedBroadcast(),可以将广播传递给其他应用。

3.3.1 Intent属性

- 组件名称(ComponentName)

这是可选项,但也是构建显式 Intent 的一项重要信息,这意味着 Intent 应当仅传递给由组件名称定义的应用组件。Intent 的这一字段是 ComponentName 对象,可以使用目标组件的完全限定类名指定此对象,其中包括应用的软件包名称。

- 操作(Action)

指定要执行的通用操作(例如,“查看”或“选取”)的字符串。

- 数据(Data)

引用待操作数据和/或该数据 MIME 类型的 URI(Uri 对象)。提供的数据类型通常由 Intent 的操作决定。
(要仅设置数据 URI,请调用 setData()。要仅设置 MIME 类型,请调用 setType()。如有必要,可以使用 setDataAndType() 同时显式设置二者。
警告:若要同时设置 URI 和 MIME 类型,请勿调用 setData() 和 setType(),因为它们会互相抵消彼此的值。请始终使用 setDataAndType() 同时设置 URI 和 MIME 类型。)

- 类别(Category)

一个包含应处理 Intent 组件类型的附加信息的字符串。可以将任意数量的类别描述放入一个 Intent 中,但大多数 Intent 均不需要类别。

- Extra

携带完成请求操作所需的附加信息的键值对。正如某些操作使用特定类型的数据 URI 一样,有些操作也使用特定的附加数据。例如,使用 ACTION_SEND 创建用于发送电子邮件的 Intent 时,可以使用 EXTRA_EMAIL键指定“目标”收件人,并使用 EXTRA_SUBJECT 键指定“主题”。

- 标志(Flags)

在 Intent 类中定义的、充当 Intent 元数据的标志。标志可以指示 Android 系统如何启动Activity(例如,Activity 应属于哪个Task )。

3.3.2 Intent的显式与隐式

- 显式 Intent

通过提供目标应用的软件包名称或完全限定的组件类名来指定可处理 Intent 的应用。通常,您会在自己的应用中使用显式 Intent 来启动组件,这是因为您知道要启动的 Activity 或服务的类名。例如,您可能会启动您应用内的新 Activity 以响应用户操作,或者启动服务以在后台下载文件。

// Executed in an Activity, so 'this' is the Context
// The fileUrl is a string URL, such as "http://www.example.com/image.png"
val downloadIntent = Intent(this, DownloadService::class.java).apply {
    data = Uri.parse(fileUrl)
}
startService(downloadIntent)

- 隐式 Intent

不会指定特定的组件,而是声明要执行的常规操作,从而允许其他应用中的组件来处理。例如,如需在地图上向用户显示位置,则可以使用隐式 Intent,请求另一具有此功能的应用在地图上显示指定的位置。

// Create the text message with a string
val sendIntent = Intent().apply {
    action = Intent.ACTION_SEND
    putExtra(Intent.EXTRA_TEXT, textMessage)
    type = "text/plain"
}

// Verify that the intent will resolve to an activity
if (sendIntent.resolveActivity(packageManager) != null) {
    startActivity(sendIntent)
}

3.4 Activity的异常生命周期

3.4.1 系统配置改变引起异常

在Android中,系统配置改变时会引起Activity销毁重建的(改了权限或者字体等系统配置后,一定要注意页面重建可能存在的风险与隐患)。在重建的流程中,原来的Activity会在销毁前调用onSaveInstanceState()保存状态。新建Activity后会调用onRestoreInstanceState()恢复状态。
在这里插入图片描述
上面是改字体的一个例子。当打开系统设置,此时我们的应用Activity走了1中的生命周期方法。确实修改了字体配置后再次打开App,走了2中的生命周期方法。

3.4.2 系统回收引起异常

在Android系统内存不足且失去焦点被系统回收时会调用onSaveInstanceState()保存状态,Activity再次创建时,会调用onRestoreInstanceState()恢复状态。

3.4.3 异常基础处理
  • 在onCreate()时判断saveInstanceState是否为空,不为空就可以从中恢复数据。
  • 根据应用场景,可以在Manifest中配置各种参数尽可能地减少由于配置参数导致的Activity异常。
  • 使用onConfigurationChanged()方法代替onRestoreInstanceState()实现恢复数据逻辑。

四. onConfigurationChanged()和onNewIntent()

4.1 onConfiguratonChanged()

当系统的配置信息发生变化时,系统会调用该方法。但是要注意,只有在Manifest文件中的对应Activity的configChanges中设置了要处理的系统配置变更类型时,该方法才会被调用。如果发生变更的配置与configChanges中设置的属性不匹配,那么Activity会被销毁并使用新的配置重建。
比如屏幕旋转前你已经在configChanges中配置了
orientation|screenSize

那么你的Activity并不会被重建,而是调用onConfigurationChanged方法。
在这里插入图片描述

4.2 onNewIntent()

当启动模式为singleTop时,Activity实例当前在栈顶时,此时会调用onNewIntent方法,调用顺序为:onPause—>onNewIntent—>onResume。
在这里插入图片描述

当启动模式为SingleInstance和singleTask时,若Activity已在任务栈时,就会调用onNewIntent方法,调用顺序为:onPause—>onNewIntent—>onRestart—>onStart—>onResume。

所以,只有SingleTop(位于栈顶),SingleTask和SingleInstance(且栈中已存在实例),再次启动它们时才会调用,仅从后台切换到前台而不再次启动的情况下不会触发onNewIntent。
在这里插入图片描述

五. onSaveInstanceState()和onRestoreInstanceState()

如果由于系统约束(而非正常的应用程序行为)导致Activity被破坏,那么尽管实际上Activity已经销毁,但是系统还是会记住它曾经存在。此时用户重新导航回它,系统会创建一个新的Activity,使用保存的状态数据来描述Activity在被销毁时的状态。
在这里插入图片描述

保存和恢复状态的方法是onSaveInstanceState()和onRestoreInstanceState(),只有在Activity被意外销毁的时候这两个方法才会触发调用,一般的Home键退到主页面再回来的时候是触发不到这两个方法的。

六. Activiy是如何启动的

6.1 Zygote的概念与作用

6.2 SystemServer的概念与作用

6.3 AMS概念、初始化、作用

6.4 Launcher概念,启动时机

6.5 Instrumentation与ActivityThread的关系

6.6 ActivityThread与AMS之间的Binder通信

6.7 AMS如何开启Activity

本部分代码见 AndroidPokkit中的chapter1

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 支持向量机非线性回归通用MATLAB程序解析 #### 一、概述 本文将详细介绍一个基于MATLAB的支持向量机(SVM)非线性回归的通用程序。该程序采用支持向量机方法来实现数据的非线性回归,并通过不同的核函数设置来适应不同类型的数据分布。此外,该程序还提供了数据预处理的方法,使得用户能够更加方便地应用此程序解决实际问题。 #### 二、核心功能与原理 ##### 1. 支持向量机(SVM) 支持向量机是一种监督学习模型,主要用于分类和回归分析。对于非线性回归任务,SVM通过引入核技巧(kernel trick)将原始低维空间中的非线性问题转换为高维空间中的线性问题,从而实现有效的非线性建模。 ##### 2. 核函数 核函数的选择直接影响到模型的性能。本程序内置了三种常用的核函数: - **线性核函数**:`K(x, y) = x'y` - **多项式核函数**:`K(x, y) = (x'y + 1)^d` - **径向基函数(RBF)**:`K(x, y) = exp(-γ|x - y|^2)` 其中RBF核函数被广泛应用于非线性问题中,因为它可以处理非常复杂的非线性关系。本程序默认使用的是RBF核函数,参数`D`用于控制高斯核函数的宽度。 ##### 3. 数据预处理 虽然程序本身没有直接涉及数据预处理的过程,但在实际应用中,对数据进行适当的预处理是非常重要的。常见的预处理步骤包括归一化、缺失值处理等。 ##### 4. 模型参数 - **Epsilon**: ε-insensitive loss function的ε值,控制回归带宽。 - **C**: 松弛变量的惩罚系数,控制模型复杂度与过拟合的风险之间的平衡。 #### 三、程序实现细节 ##### 1. 函数输入与输出 - **输入**: - `X`: 输入特征矩阵,维度为(n, l),其中n是特征数量,l是样本数量。 - `Y`: 目标值向量,长度为l。 - `Epsilon`: 回归带宽。 - `C`: 松弛变量的惩罚系数。 - `D`: RBF核函数的参数。 - **输出**: - `Alpha1`: 正的拉格朗日乘子向量。 - `Alpha2`: 负的拉格朗日乘子向量。 - `Alpha`: 拉格朗日乘子向量。 - `Flag`: 标记向量,表示每个样本的类型。 - `B`: 偏置项。 ##### 2. 核心代码解析 程序首先计算所有样本间的核矩阵`K`,然后构建二次规划问题并求解得到拉格朗日乘子向量。根据拉格朗日乘子的值确定支持向量,并计算偏置项`B`。 - **核矩阵计算**:采用RBF核函数,通过`exp(-(sum((xi-xj).^2)/D))`计算任意两个样本之间的相似度。 - **二次规划**:构建目标函数和约束条件,使用`quadprog`函数求解最小化问题。 - **支持向量识别**:根据拉格朗日乘子的大小判断每个样本是否为支持向量,并据此计算偏置项`B`。 #### 四、程序扩展与优化 - **多核函数支持**:可以通过增加更多的核函数选项,提高程序的灵活性。 - **自动调参**:实现参数自动选择的功能,例如通过交叉验证选择最优的`Epsilon`和`C`值。 - **并行计算**:利用MATLAB的并行计算工具箱加速计算过程,特别是当样本量很大时。 #### 五、应用场景 该程序适用于需要进行非线性回归预测的场景,如经济预测、天气预报等领域。通过调整核函数和参数,可以有效应对各种类型的非线性问题。 ### 总结 本程序提供了一个支持向量机非线性回归的完整实现框架,通过灵活的核函数设置和参数调整,能够有效地处理非线性问题。对于需要进行回归预测的应用场景,这是一个非常实用且强大的工具。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值