文章目录

  • Activity介绍
  • 生命周期
  • Activity的启动模式
  • Activity的最佳实践(拓展学习)
    • 知晓当前是在哪一个 Activity
    • 随时随地退出程序
    • 启动 Activity 的最佳写法

Activity介绍

介绍
Activity 是 Android 系统的核心组件(系统的核心组件是由系统进行管理和维护的),用于处理 UI 相关的业务

如何创建 Activity
1、自定义类,继承自 Activity
2、注册,在 AndroidMenifest.xml 文件中,在<application>节点下,创建新的<activity>节点,并指定android:name属性,取值为自定义Activity类的包名和类名。如果想作为启动的第一个Activity,则在节点下增加<intent-filter>,修改标题栏的名称可以增加label

启动 Activity

Intetnt i = new Intent(当前窗口对象,目标窗口对象);
startActivity(i);

举例1:打开新的 Activity

现在我们在 MainActivity 中打开一个新窗口 SecondActivity,然后点击 SecondActivity 中按钮再打开 MainActivity

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="主窗口"android:textSize="20sp"android:textColor="#222222"android:gravity="center"/><Buttonandroid:id="@+id/button1"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="启动第二个窗口"android:layout_marginTop="20dp"/></LinearLayout>

MainActivity

/*
* 应用启动时,会启动主窗口
* 系统会新建主窗口对象
* 然后自动调用onCreate()方法
* */
public class MainActivity extends AppCompatActivity {private Button button;/** 在窗口父类 Activity 中定义的方法* 按照安卓开发规范,在子类中,必须重写* 必须调用父类的 onCreate()方法:super.onCreate(savedInstanceState);* */@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);//从父类继承的方法//在当前窗口中显示指定界面setContentView(R.layout.activity_main);//界面显示后,从当前显示的界面上获得控件button = findViewById(R.id.button1);//给按钮设置监听器button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//使用外部类对象的thisIntent intent = new Intent(MainActivity.this, SecondActivity.class);startActivity(intent);}});}
}

activity_second.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center"android:text="第二个窗口"android:textColor="#222222"android:textSize="20sp" /><Buttonandroid:id="@+id/button2"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="20dp"android:text="启动主窗口" /></LinearLayout>

SecondActivity

public class SecondActivity extends AppCompatActivity {private Button button;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_second);button = findViewById(R.id.button2);//这里使用了 lambda 表达式button.setOnClickListener(view -> {Intent intent = new Intent(SecondActivity.this, MainActivity.class);startActivity(intent);});}
}

AndroidManifest.xml中进行注册

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.testapplication"><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.AppCompat.Light.NoActionBar"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><activity android:name=".SecondActivity" /></application></manifest>

运行程序:

停止Activity
上边的例子中,从第二个窗口跳转主窗口(SecondActivity 跳转 MainActivity)时,是又打开了新的 MainActivity ,其实我们直接把第二个窗口(SecondActivity)关掉就回到了主窗口(MainActivity)。

在 Activity 内部调用 finish() 方法,即可停止/销毁当前 Activity。

修改 SecondActivity 中按钮点击事件

button.setOnClickListener(view -> {finish();});

运行结果:

调用 finish() 方法的效果等同于按下设备上的 Back 键,导致 Activity 的生命周期方法执行:onPause()->onStop()->onDestroy()(生命周期方法的介绍在下面)

停止当前应用中所有Activity
可以使用 List 集合记录下每一个激活的 Activity 对象,当需要全部停止时,遍历该集合,依次调用各 Activity 对象的 finish()方法

记录 Activity 对象:在每一个 Activity 的onCreate()中,将当前 Activity 对象添加到List 集合,在每一个 Activity 的onDestory()中,将当前的 Activity 对象从 List 集合中移除

生命周期

Activity 的生命周期表现为会执行一系列的方法,包括:

  • onCreate()//创建时
  • onStart()
  • onRestart()
  • onResume()
  • onPause()
  • onStop()
  • onDestroy()//销毁时

我们可以在刚才的两个 Activity 中重写以上方法,并进行打印,来观察2个 Activity 切换时的生命周期

从第一个 Activity 跳转到第二个 Activity 时(简写 A -> B):

D/A: onCreate()
D/A: onStart()
D/A: onResume()
D/A: onPause()D/B: onCreate()
D/B: onStart()
D/B: onResume()D/A: onStop()

此时显示在 B,现在直接按返回键,来销毁 B

D/B: onPause()D/A: onRestart()
D/A: onStart()
D/A: onResume()D/B: onStop()
D/B: onDestroy()

如果 SecondActivity 中按钮点击依旧跳转新的 MainActivity

D/SecondActivity: onPause()
D/MainActivity: onCreate()
D/MainActivity: onStart()
D/MainActivity: onResume()
D/SecondActivity: onStop()

现在跳转的 MainActivity 已经不是原来的 Activity 了,我们可以根据 hashCode 判断是不是相同 Activity,可在 onCreate() 中打印验证下

this.hashCode()

总结生命周期执行顺序

  • 当 Activity 第一次激活时,onCreate()->onStart()->onResume()
  • Activity 被置于后台时(例如回到桌面时),onPause()->onStop()
  • Activity回到前台时(例如从桌面切回Activity时),onRestart()->onStart()->onResume()
  • 退出Activity时,onPause()->onStop()->onDestroy()
  • 查看 Activity 是否是同一个,可以根据this.hashCode()来区分

根据上边可以总结出Activity的状态

  1. 运行态:表现为 Activity 处于前台,可见,可控,生命周期停留在onResume()
  2. 暂停态:表现为 Activity 局部可见,但不可控,生命周期方法停留在onPause()方法,通常是被另一个非全屏的Activity遮挡导致
  3. 停止态:表现为该 Activity 被置于后台,完全不可见,生命周期停留在onStop()
  4. 终止态:表现为该 Activity 已经被回调了onDestroy()方法,即已经销毁

在停止状态前,会短暂的表现为暂停态,onPause()是 Activity 被遮挡时调用的方法,真正被置于后台时调用的方法是onStop()

Activity的启动模式

Activity 的启动模式决定了 Activity 实例/对象的数量。在默认情况下,每次激活Activity,都会创建新的实例/对象。

这里首先需要了解 任务栈/回退栈 的相关概念

任务栈/回退栈
记录了同一个任务中,各个已经激活的 Activity 的先后顺序,以至于用户在点击设备上的 Back 键时,系统能知道需要将曾经打开的哪个 Activity 恢复到前台

压栈
激活新的 Activity 时,默认新的 Activity 会执行压栈,压栈后,该 Activity 将处于栈顶位置,即该 Activity 显示在前台,栈内其它 Activity 均被置于后台

弹栈
当前 Activity 被销毁时,栈内其他 Activity 均向上弹起,原栈顶的 Activity 被销毁的同时,原排名第二的 Activity 将获得栈顶位置

如何配置启动模式
在 AndroidManifest.mxl 中,为<activity>节点配置android:launchMode属性即可配置 Activiy 的启动模式

启动模式
standard:(默认)标准模式,每次激活 Activity,都会创建新的实例/对象

singleTop:栈顶唯一,表现为当 Activity 处于栈顶位置时,反复激活并不会创建新的实例,也不会出现压栈操作,反之,当 Activity 不处于栈顶位置时,激活时会创建新的实例,并压栈

singleTask:任务栈内唯一,表现为当任务栈中没有当前 Activity 时,会创建新的实例,并压栈,反之,当任务栈中已经存在当前 Activity 时,不会创建新的实例,原本在栈内处于该 Activity 偏上方的其他 Activity 将全部会被强制出栈,使得该被激活的 Activity 获得栈顶位置

singleInstance:实例唯一,该 Activity 的实例最多只存在1个,该 Activity 将强制独占1个新的任务栈,且该任务栈中有且仅有1个 Activity

测试SingleTop

修改 activity_main.xml,增加一个显示 hashcode 的 TextView 和 一个重复激活 MainActivity 的按钮

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center"android:text="MainActvity"android:textColor="#222222"android:textSize="20sp" /><TextViewandroid:id="@+id/tv_hash_code"android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center"android:textColor="#222222"android:textSize="20sp" /><Buttonandroid:id="@+id/button1"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="20dp"android:text="激活MainActivity" /><Buttonandroid:id="@+id/button2"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="20dp"android:text="激活SecondActivity" /></LinearLayout>

修改 MainActivity,让 button2 重复激活 MainActivtity,让 TextView 显示 hashCode

public class MainActivity extends AppCompatActivity {private Button button1;private Button button2;private TextView tv_hash_code;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);tv_hash_code = findViewById(R.id.tv_hash_code);tv_hash_code.setText(this.hashCode()+"");button1 = findViewById(R.id.button1);button1.setOnClickListener(view -> {Intent intent = new Intent(MainActivity.this, MainActivity.class);startActivity(intent);});button2 = findViewById(R.id.button2);button2.setOnClickListener(view -> {Intent intent = new Intent(MainActivity.this, SecondActivity.class);startActivity(intent);});}
}

修改 AndroidManifest.xml 中 MainActivity 启动模式为 singleTop

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.testapplication"><application......><activity android:name=".MainActivity"android:launchMode="singleTop"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity>......</application></manifest>

运行结果:

点击激活 MainActivity 按钮,页面中的 hashCode 并没有改变,也就说明并没有启动新的Activity

打开 SecondActivity,然后点击 SecondActivity 中的打开 MainActivity 按钮,发现hashCode 已经跟第一次打开 MainActivity 不同了,所以这是打开了一个新的 MainActivity

测试singleTask

现在修改两个 Activity 的启动模式如下

<activity android:name=".MainActivity"android:launchMode="standard">......
</activity><activity android:name=".SecondActivity"android:launchMode="singleTask"/>

运行程序:

启动应用打开了 MainActivity,hashCode 为 313
然后点击页面上的激活 MainActivity,hashcode 为 393
再点击激活 SecondActivity,hashcode 为 209
点击 SecondActivity 中的按钮激活 MainActivity,hashcode 为 100
再点击 MainActivity 中按钮激活新 MainActivity,hashcode 为 977

此时任务栈的任务如下:

此时在打开的 MainActivity 中打开 SecondActivity,hashCode为 209,跟第一次打开的相同

现在 SecondActivity 处于栈顶,而之前处于它上面的两个 MainActivity 已经被销毁了

我们可以验证一下,现在按 Back 键,或者手势返回,MainActivity 的 hashcode 应该是 393

测试singleInstance
指定为 singleInstance 模式的 Activity 会启用一个新的返回栈来管理这个 Activity。

使用情景如下:假设我们程序中有一个 Activity,是允许其他程序调用的,如果想实现其他程序和我们程序共享这个 Activity 实例,在这种模式下,会有一个单独的返回栈来管理这个 Activity,不管哪个应用程序访问这个 Activity,都公用一个返回栈,也解决了共享 Activity 实例的问题

将 SecondActivity改为 singleInstance

另外当Activity的启动模式被配置为 singleTask 或 singleInstance 时,执行效果可能受到android:taskAffinity(亲属关系)的影响

Activity的最佳实践(拓展学习)

以下是 《第一行代码 Android 第3版》中的例子,由于是 kotlin 语言,所以做为拓展来学

知晓当前是在哪一个 Activity

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

javaClass表示获取当前实例的 Class 对象,相当于在 Java 中调用 getClass 方法,然后再调用 simpleName 获取当前实例的类名

现在让 BaseActivity 成为项目所有 Activity 的父类,为了使其能够被继承,在类名前加上 open关键字

然后让其他 Activity 继承 BaseActivity 即可

class MainActivity : BaseActivity() {......
}

再次运行程序,每当我们进入一个 Activity 该 Activity 类名就会被打印出来

随时随地退出程序

新建一个单例类 ActivityCollector 作为 Activity 的集合

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()//可以加上杀掉进程的代码,保证程序完全退出//android.os.Process.killProcess(android.os.Process.myPid())}
}

我们调用 activity.isFinishing 来判断 Activity 是否正在销毁中,因为 Activity 还可能通过按下 Back 键等方式被销毁。如果 Activity 没有正在销毁中,我们再去调用它的 finish() 方法来销毁它

接下来修改 BaseActivity 中代码

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

在任何页面想退出程序只需调用 ActivityCollector.finishAll()

启动 Activity 的最佳写法

从 FirstActivity 启动 SecondActivity 需要传递哪些数据,你还要去阅读代码很麻烦,换种写法就可以轻松解决

class SecondActivity : BaseActivity() {......companion object{fun actionStart(context: Context,data1:String,data2:String){val intent = Intent(context,SecondActivity::class.java)intent.putExtra("param1",data1)intent.putExtra("param2",data2)context.startActivity(intent)}}
}

这样写的好处是 SecondActivity 所需数据在方法参数中全部体现了,另外还简化了启动 Activity 的代码

button.setOnClickListener {SecondActivity.actionStart(this,"data1","data2")
}

【达内课程】Activity 详解相关推荐

  1. 【阿里云课程】详解深度学习优化:泛化与正则化,学习率与最优化

    大家好,继续更新有三AI与阿里天池联合推出的深度学习系列课程,本次更新内容为第6课中两节,介绍如下: 第1节:泛化与正则化 第1节课内容为:泛化与正则化,讲述泛化的概念与重要性,各种正则化方法,包括显 ...

  2. [安卓基础] 009.组件Activity详解

    组件Activity详解 这篇文章学到得内容 1.什么是Activity 2.Activity的生命周期 3.如何保存Activity的状态 4.Activity之间切换时,相互之间生命周期的执行顺序 ...

  3. 影视后期行业概述、制作流程、岗位划分、薪资待遇、课程介绍详解

    影视后期行业概述.制作流程.岗位划分.薪资待遇.课程介绍详解 本篇围绕影视后期行业概念定义.应用与细分.影视制作流程.市场上职责岗位划分.影视后期课程详情.影视后期薪资结构与前景.授课方式与课程划分. ...

  4. CS144课程实验详解-lab0-第一部分

    CS144课程实验详解-lab0-第一部分 配置环境 下载并安装VirtualBox 下载实验虚拟机cs144_vm.ova并导入VirtualBox 额外提示-图形用户界面 额外提示-共享文件夹 手 ...

  5. Android9.0 Launcher启动Activity详解(一)

    一.开始 Launcher中点击应用图标启动Activity,其开始方法是 public boolean startActivitySafely(View v, Intent intent, Item ...

  6. Coursera? EdX? 五大在线课程平台详解

    这里写自定义目录标题 1. Coursera? EdX? 五大在线课程平台详解 1.1. Coursera 1.2. EdX 1.3. Udemy 1.4. Udacity 1.5. Khan Aca ...

  7. Android 之 Activity 详解

    最近在学习Android开发方面的知识,整理了一下关于Android中Activity方面的知识,也算是对自己学的知识进行了总结.Activity 在 Android开发中有着极其重要的位置,Acti ...

  8. android 之Fragment(轻量级的Activity)详解

    创建一个Fragment: Fragment的几个子类. (1)对话框:DialogFragment (2)列表:ListFragment (3)非选项设置:PreferenceFragment (4 ...

  9. android 之四大组件的Activity详解

    Activity的生命周期: Activity的四种基本状态: (1) 运行态(Running) Activity处在最前端,用户可见可获得焦点 (2) 暂停态(Paused) Activity处在最 ...

最新文章

  1. 【发现】Pandora's Box Puzzle Game of the Year Edition 原版镜像
  2. javaweb:servlet的多线程同步问题
  3. 如何在Android模拟器上安装和卸载APK程序包
  4. 小试牛刀Matplotlib
  5. Mastering Android NDK Build System - Part 1: Techniques with ndk-build
  6. Markdown列表
  7. 《Pro/ENGINEER野火版5.0从入门到精通》——2.5 设置零件单位
  8. 14.1178亿人 流动人口超3亿 “大国普查”这些数据很重要
  9. POI 导出导入工具类介绍
  10. python 获取唯一值_从Python列表中获取唯一值
  11. classloader隔离练习
  12. 常用的做网站软件、网站制作软件分享
  13. TCP/IP报文格式详解
  14. 如何判断对方列表里是不是好友_QQ怎么知道自己是不是对方好友
  15. 电路串联和并联图解_串联电路与并联电路的区别
  16. HTML表格的单元格合并
  17. 我迟早被这些AI绘画笑死...
  18. 深度学习—利用TensorFlow2实现狗狗品种品种(DenseNet121实现)
  19. 手机微信登录的服务器繁忙请稍后再试,微信操作太频繁请稍后再试怎么办(登不上去要等多久)...
  20. 为什么自来水按立方米收费?

热门文章

  1. 交流电的有效值 RMS值 均方根值
  2. 微机计算机原理及应用ppt,微机原理及应用-第一章 计算机基础知识课件.ppt
  3. mac版向日葵远程控制怎么用 向日葵远程控制软件mac版使用图文教程
  4. 第八周项目32-对程序运行结果的理解
  5. 解决 QT “调试器未设置”问题
  6. 以太网链路聚合与交换机堆叠、集群(浅谈、总结)
  7. mysql中视图与真实表的区别,数据库表/视图/同义词的区别
  8. 【搜索】:罗纳尔多和C罗是一个人吗?
  9. 恒玄BES调试笔记-BES2500蓝牙相关参数设定
  10. FAQ |百度超级链Dapp互通计划答疑