2019独角兽企业重金招聘Python工程师标准>>>

启动一个Activity


使用startActivity(Intent intent)。 intent指定了你想要启动的activity,或者指定了你想展现的动作(系统帮你选择合适的activity,它可能来自于其他的程序)。 intent也可以携带比较小量的数据,用于启动acitivity。

在你自己的应用中,你经常会通过创建一个明确的intent,简单地启动一个已知的activity,。这个intent指定了activity的类名。 例如下面演示了如何启动一个叫SignInActivity的activity:

Intent intent = new Intent(this, SignInActivity.class);
startActivity(intent);

然而,你的程序可能想要展示某些动作,例如发邮件,短信,微博,或者使用你activity中的数据。 这时候,你就不应该使用自己的activity来做这些工作。你应该调用系统中其他程序提供的响应功能。 这是intent真正体现其价值的地方。你可以创建一个描述了响应动作的intent,然后系统来为你挑选完成任务的程序。 如果有多个选择,系统会提示用户进行选择。例如你想让用户发邮件,你可以创建下面的intent:

Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
startActivity(intent);

EXTRA_EMAIL 是一个邮件intent中添加的额外字符串数组,它指定了邮件该发给哪些邮件地址。当一个邮件程序响应了这个intent, 它将读取这些地址,并把他们放置到邮件表单的被发送人栏。这时,邮件程序被启动。当用户完成了发送操作,你的activity会被恢复。

启动一个带返回结果的activity

有时候,你想要启动一个activity,并从这个activty获得一个结果。 这时,要通过 startActivityForResult() (取代startActivity()) 来启动activity。 然后通过实现onActivityResult()回调方法来获得返回后的结果。 当这个后续的activity被关闭,它将发送一个 Intent 给 onActivityResult() 方法。

例如,你可能想要取一个联系人的信息。下面介绍怎么创建intent并处理结果:

private void pickContact() {// Create an intent to "pick" a contact, as defined by the content provider URIIntent intent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI);startActivityForResult(intent, PICK_CONTACT_REQUEST);
}@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {// If the request went well (OK) and the request was PICK_CONTACT_REQUESTif (resultCode == Activity.RESULT_OK && requestCode == PICK_CONTACT_REQUEST) {// Perform a query to the contact's content provider for the contact's nameCursor cursor = getContentResolver().query(data.getData() , new String[] {Contacts.DISPLAY_NAME}, null, null, null);if (cursor.moveToFirst()) { // True if the cursor is not emptyint columnIndex = cursor.getColumnIndex(Contacts.DISPLAY_NAME);String name = cursor.getString(columnIndex);// Do something with the selected contact's name...}}
}

这个例子展示了使用onActivityResult() 来获取结果的基本方法。 第一步要判断请求是否被成功响应,通过判断resultCode 是不是RESULT_OK, 然后判断这个响应是不是针对相应的请求,此时只要判断requestCode和发送时提供的第二个参数 startActivityForResult() 是否相匹配。 最后,查询 Intent中的data信息。 (data 参数)。

这个过程中,ContentResolver 开启了一个查询而不是content provider, 它返回一个 Cursor ,这将允许数据被读取。更多content provider相关信息,请查阅Content Providers 文档。

关于intent的更多信息, 查看 Intents and Intent Filters 文档。

关闭Activity


你可以通过调用finish() 来终止activity。 你也可以调用finishActivity() 来终止你之前启动了的一个独立activity。

注意: 多数情况下,你不应该明确地通过这些方式来关闭acitivity。 就像下面要讨论的activity的生命周期。系统会为你管理。所以你不必关闭他们。 调用这些方法将有悖于用户体验。它们仅用于你绝对不想让用户再返回这个activity的实例。

管理Activity的生命周期


activity可能处于三种基本的状态:

  1. Resumedactivity    在屏幕的前台并且拥有用户的焦点。(这个状态有时也被叫做“running”)

  2. Paused    另一个activity在前台并拥有焦点,但是本activity还是可见的。 也就是说,另外一个activity覆盖在本activity的上面,并且那个activity是部分透明的或没有覆盖整个屏幕。 一个paused的activity是完全存活的(Activity 对象仍然保留在内存里,它保持着所有的状态和成员信息,并且保持与window manager的联接),但在系统内存严重不足的情况下它能被杀死。

  3. Stopped    本activity被其它的activity完全遮挡住了(本activity目前在后台)。 一个stopped的activity也仍然是存活的(Activity 对象仍然保留在内存中,它保持着所有的状态和成员信息,但是不再与window manager联接了)。 但是,对于用户而言它已经不再可见了,并且当其它地方需要内存时它将会被杀死。

如果activity被paused或stopped了,则系统可以从内存中删除它,通过请求finish(调用它的 finish() 方法)或者直接杀死它的进程。 当这个activity被再次启动时(在被finish或者kill后),它必须被完全重建。

实现生命周期回调方法

当一个activity在上述描述的状态之间转换时,它将通过各种回调方法来获得通知。 所有的回调方法都是钩子(hook),当activity状态发生改变时你都可以 重写这些方法来执行对应的工作。 以下的activity提纲包含了所有基本的生命周期方法:

public class ExampleActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);// The activity is being created. }@Override protected void onStart() {super.onStart();// The activity is about to become visible.} @Override protected void onResume() { super.onResume();// The activity has become visible (it is now "resumed"). } @Override protected void onPause() { super.onPause(); // Another activity is taking focus (this activity is about to be "paused"). } @Override protected void onStop() { super.onStop(); // The activity is no longer visible (it is now "stopped") } @Override protected void onDestroy() { super.onDestroy(); // The activity is about to be destroyed. }
}

注意:实现这些生命周期方法时,必须保证在其它代码之前首先调用一下父类的方法,如上例所示。

总体来讲,这些方法定义了一个activity的完整的生命周期。 通过实现这些方法,你可以监控activity生命周期中三个嵌套的循环:

  • activity的完整生存期会在 onCreate() 调用和 onDestroy() 调用之间发生。 你的activity应该在 onCreate() 方法里完成所有“全局global”状态的设置(比如定义layout), 而在onDestroy() 方法里释放所有占用的资源。 例如,如果你的activity有一个后台运行的线程,用于从网络下载数据,那么你应该在 onCreate() 方法里创建这个线程并且在 onDestroy() 方法里停止这个线程。

  • activity的可见生存期会在 onStart() 调用和 onStop() 调用之间发生。在这期间,用户可在屏幕上看见这个activity并可与之交互。 例如,当一个新的activity启动后调用了 onStop() 方法,则这个activity就无法被看见了。 在这两个方法之间,你可以管理那些显示activity所需的资源。例如,你可以在 onStart() 方法里注册一个 BroadcastReceiver 用于监控影响用户界面的改动。并且当用户不再看到你的显示内容时,在 onStop() 方法里注销掉它。 系统会在activity的整个生存期内多次调用 onStart() 和onStop(), 因为activity可能会在显示和隐藏之间不断地来回切换。

  • activity的前台生存期会在 onResume() 调用和 onPause() 之间发生。在这期间,activity是位于屏幕上所有其它的activity之前,并且拥有用户的输入焦点。 activity可以频繁地进入和退出前台——例如, 当设备进入休眠时或者弹出一个对话框时, onPause() 就会被调用。因为这个状态可能会经常发生转换,为了避免切换迟缓引起的用户等待,这两个方法中的代码应该相当地轻量化。

图1说明了activity在状态之间可能行走的这些循环和路径。矩形代表了你可以实现的回调方法,用于activity状态转换时执行相应操作。

同样的生命周期回调方法已经在表1中列出了,该表更详细地描述了每个回调方法,并且指明了每个方法在activity的全生命周期中的位置, 包括回调方法完成后系统是否会杀死这个activity。

表 1.activity生命周期回调方法汇总

方法 描述 之后可否被杀死? 下一个方法
onCreate() activity第一次被创建时调用。在这里你应该完成所有常见的静态设置工作——创建view、绑定list数据等等。 本方法传入一个包含了该activity前一个状态的Bundle对象(如果之前已捕获了状态的话,详见后面的保存Activity状态)。

下一个回调方法总是onStart()。

onStart()
onRestart() activity被停止后、又再次被启动之前调用。

下一个回调方法总是onStart()

onStart()
onStart() activity要显示给用户之前调用。

如果activity进入前台,则下一个回调方法是onResume();如果进入隐藏状态,则下一个回调方法是onStop()。

onResume() 或 onStop()
onResume() activity开始与用户交互之前调用。这时activity是在activity栈的顶端,用户可以向其中输入。

下一个回调方法总是onPause()。

onPause()
onPause() 当系统准备启动另一个正在恢复的activity时调用。这个方法通常用于把未保存的改动提交为永久数据、停止动画播放、以及其它可能消耗CPU的工作等等。 它应该非常迅速地完成工作,因为下一个activity在本方法返回前是不会被恢复运行的。

如果activity返回前台,则下一个回调方法是onResume();如果进入用户不可见状态,则下一个是onStop()

可以 onResume() 或 onStop()
onStop() 当activity不再对用户可见时调用。原因可能是它即将被销毁、或者其它activity(已有或新建的)被恢复运行并要覆盖本activity。

如果activity还会回来与用户交互,则下一个回调方法是onRestart();如果这个activity即将消失,则下一个回调方法是onDestroy()

可以 onRestart() 或 onDestroy()
onDestroy() 在本activity被销毁前调用。这是activity收到的最后一个调用。 可能是因为activity完成了工作(有些人在这里调用finish()), 也可能是因为系统为了腾出空间而临时销毁activity的本实例。 可以利用isFinishing() 方法来区分这两种情况。 可以

标为“之后可否被杀死?”的列指明了系统是否可以在这个方法返回之后的任意时刻杀掉这个activity的宿主进程, 而不再执行其它流程上的activity代码。 有三个方法是标为“可以”:( onPause()、 onStop()、 和onDestroy())。 因为onPause()是三个方法中的第一个, 一旦activity被创建, onPause() 就是进程可以被杀死之前最后一个能确保被调用的方法 ——如果系统在某种紧急情况下必须回收内存,则 onStop() 和onDestroy() 可能就不会被调用了。因此,你应该使用 onPause() 来把至关重要的需长期保存的数据写入存储器(比如用户所编辑的内容)。 不过,应该对必须通过 onPause() 方法进行保存的信息有所选择,因为该方法中所有的阻塞操作都会让切换到下一个activity的停滞,并使用户感觉到迟缓。

“之后可否被杀死?”列中标为“否”的方法,在它们被调用时的那一刻起,就会保护本activity的宿主进程不被杀掉。 因此,只有在 onPause() 方法返回时至 onResume() 方法被调用时之间,activity才会被杀掉。直到 onPause() 再次被调用并返回时,activity都不会再次允许被杀死。

Note:表1中标明的技术上不“可杀”的activity仍然有可能会被系统杀死——但那只有在没有任何资源的极端情况下才会发生。 什么时候activity会被杀掉,已在文档进程和线程里详细说明了。

保存activity的状态

管理Activity生命周期一节中已简单提到,当一个activity被paused或者stopped时,activity的状态可以被保存。 的确如此,因为 Activity 对象在paused或者stopped时仍然被保留在内存之中——它所有的成员信息和当前状态都仍然存活。 这样用户在activity里所作的改动全都还保存着,所以当activity返回到前台时(当它“resume“),那些改动仍然有效。

不过,如果系统是为了回收内存而销毁activity,则这个 Activity 对象就会被销毁,这样系统就无法简单地resume一下就能还原完整状态的activity。 如果用户要返回到这个activity的话,系统必须重新创建这个Activity 对象。可是用户并不知道系统是先销毁activity再重新创建了它的,所以,他很可能希望activity完全保持原样。 这种情况下,你可以保证activity状态的相关重要信息都由另一个回调方法保存下来了,此方法让你能保存activity状态的相关信息: onSaveInstanceState()。

在activity变得很容易被销毁之前,系统会调用 onSaveInstanceState()方法。 调用时系统会传入一个Bundle对象, 你可以利用 putString() 之类的方法,以键值对的方式来把activity状态信息保存到该Bundle对象中。 然后,如果系统杀掉了你的application进程并且用户又返回到你的activity,系统就会重建activity并将这个 Bundle 传入onCreate() 和onRestoreInstanceState() 中,你就可以从 Bundle 中解析出已保存信息并恢复activity状态。如果没有储存状态信息,那么传入的 Bundle 将为null(当activity第一次被创建时就是如此)。

注意: activity被销毁之前,并不能确保每次都会调用 onSaveInstanceState() ,因为存在那些不必保存状态的情况(比如用户使用BACK键离开了你的activity,因为用户明显是关了这个activity)。 如果系统要调用 onSaveInstanceState() 方法,那么它通常会在 onStop() 方法之前并且可能是在 onPause() 之前调用。

不过,即使你没有实现 onSaveInstanceState() 方法,有些activity状态还是会通过 Activity 类默认实现的onSaveInstanceState() 方法保存下来。特别的是,默认为layout中的每个 View 实现了调用相应的onSaveInstanceState() 方法,这允许每一个view提供自己需被保存的信息。 几乎Android框架下所有的widget都会在适当的时候实现该方法,这样,任何UI上可见的变化都会自动保存下来,并在activity重建后自动恢复。 例如,EditText widget会保存所有用户已经输入的文本, CheckBoxwidget 也会保存是否被选中。你所要做的工作仅仅是为每一个你想要保存其状态的widget提供一个唯一的ID(就是 android:id 属性)。如果这个widget没有ID的话,系统是无法保存它们的状态的。

通过把android:saveEnabled 设置为"false",或者调用 setSaveEnabled() 方法,你也可以显式地阻止layout中的某个view保存状态。 通常不应该禁用保存,不过假如你需要恢复activity UI的各个不同的状态,也许可以这么做。

尽管缺省实现的 onSaveInstanceState() 方法会保存activity UI的有用信息,你仍然需要覆盖它来存入更多的信息。 例如,你可能需要保存在activity生命周期中改变的成员变量值(可能是关于UI恢复的值,但是默认情况下,存放这些UI状态的成员变量值是不会被恢复的)。

因为默认实现的 onSaveInstanceState() 方法已经帮你保存了一些UI的状态,所以如果你重写此方法是为了保存更多的状态信息,那么在执行自己的代码之前应该确保先调用一次父类的 onSaveInstanceState() 方法。同理,如果重写 onRestoreInstanceState() 的话,也应该调用一次父类的该方法,这样缺省的代码就能正常恢复view的状态了。

注意:因为 onSaveInstanceState() 并不保证每次都会被调用,所以你应该只用它来记录activity的一些临时状态信息(UI的状态)——千万不要用它来保存那些需要长久保存的数据。 替代方案是,你应该在用户离开activity的时候利用 onPause() 来保存永久性数据(比如那些需要存入数据库里的数据)。

配置改动后的处理

设备的某些配置可能会在运行时发生变化(比如屏幕方向、键盘可用性以及语言)。 当发生这些变化时,Android会重建这个运行中的activity(系统会调用 onDestroy() ,然后再马上调用 onCreate() )。这种设计有助于应用程序适用新的参数配置,通过把你预置的可替换资源(比如对应各种屏幕方向和尺寸的layout)自动重新装载进入应用程序的方式来实现。

如果你采取了适当的设计,让activity能够正确地处理这些因为屏幕方向而引起的重启,并能如上所述地恢复activity状态, 那么你的应用程序将对生命周期中其它的意外事件更具适应能力。

处理这类重启的最佳方式,就是利用 onSaveInstanceState() 和onRestoreInstanceState() (或者 onCreate() )进行状态的保存和恢复。

多activity的合作

当activity启动另一个activity时,它俩生命周期的状态都会发生转换。 第一个activity paused并stopped(尽管它也可能不会被stopped,如果它仍然后台可见的话),而另一个activity是被created。 如果这两个activity共用了保存在磁盘或其它地方的数据,那么请明白:在第二个activity被created之前,第一个activity还没有完全被stopped,这点非常重要。第二个activity的启动进程与第一个activity的关闭进程在时间上会发生重叠。

生命周期回调方法的顺序是很明确的,特别是两个activity位于同一个进程中、一个启动另一个的时候。 下面就是Aactivity A启动Activity B时的操作顺序:

  1. Activity A的 onPause()方法,如果活动后台不可见的话,运行onStop(),否则不运行。

  2. Activity B的 onCreate() ,onStart() 和onResume() 方法依次运行。(Activity B现在获得用户焦点。)

转载于:https://my.oschina.net/JiangTun/blog/639976

Android学习笔记系列四2 —— Activity的生命周期相关推荐

  1. Android学习笔记(四):在Activity中跳转--Intent的使用

    Android学习笔记(四):在Activity中跳转--Intent的使用 上篇,我们实战了一个很小的项目BMI,通过BMI这个项目,可以很好的理解Activity的程序结构,以方便后面高级API的 ...

  2. Android面试专题系列(四):Activity之间如何进行通信→LiveDataBus

    不诗意的女程序媛不是好厨师~ 转载请注明出处,From李诗雨-https://blog.csdn.net/cjm2484836553/article/details/105147592 <And ...

  3. 【Monica的android学习之路】四大组件的生命周期

    [Monica的android学习之路]四大组件的生命周期 1. Service 1.1 启动service 1.1.1 startService 1.1.2 bindService 1.2 死亡回调 ...

  4. Servlet和HTTP请求协议-学习笔记01【Servlet_快速入门-生命周期方法、Servlet_3.0注解配置、IDEA与tomcat相关配置】

    Java后端 学习路线 笔记汇总表[黑马程序员] Servlet和HTTP请求协议-学习笔记01[Servlet_快速入门-生命周期方法.Servlet_3.0注解配置.IDEA与tomcat相关配置 ...

  5. android中的横竖屏切换,Android中横竖屏切换时Activity的生命周期

    Android中横竖屏切换时Activity的生命周期执行情况 1.默认情况下生命周期 (1)第一次进入界面 11-17 13:55:18.452: E/ImageListActivity(10586 ...

  6. Android笔记之Android基本控件布局与Activity的生命周期

    前言 喜欢安卓里千奇百怪的app,酷炫的UI或者好玩的游戏.想知道那些软件是如何做的,为什么我在微博里发一条消息,就能一直存在网上,让别人看到?为什么我点击一个按钮就出现了一个效果,某个功能?为什么滑 ...

  7. Android开发艺术探索笔记(一) Activity的生命周期和启动模式(1)

    Activity作为Android开发中最常用的一个组件,是Android开发人员必须熟悉且掌握的重要内容.同时Activity也是在面试中经常被问到的一个方向.因此,掌握Activity的重要性也不 ...

  8. Pro Android学习笔记(四八) ActionBar(1) Home图标区

    ActionBar在Android 3.0 SDK中为平板引入,在4.0中也可以在phone中使用.在title中提供类似tab和菜单的效果,有三种形式:Tabbed action bar,list ...

  9. android应用开发(22)---Activity的生命周期

    了解活动生命周期 当用户浏览,浏览并返回到您的应用程序时,应用程序中的 Activity实例将在其生命周期中的不同状态中转换.的Activity类提供了一些回调允许活动知道一个状态已经改变的:该系统被 ...

最新文章

  1. 儿童学python编程入门用途-干货 | 看了此文,家长就知道为啥要让孩子学Python?...
  2. JSON Undefined 问题
  3. boost::make_iterator_range用法的测试程序
  4. 全国计算机等级考试题库二级C操作题100套(第64套)
  5. oracle共享服务器模式的图,Oracle 11g笔记——专有服务器、共享服务器模式
  6. iOS 6 的5个新特性创建杀手级应用
  7. fasterrcnn tensorflow代码详解_pytorch目标检测代码的一些bug调试
  8. 20155201 实验四《Java面向对象程序设计》实验报告
  9. windows程序窗体创建流程模型A--发送自定义消息逻辑上出现Bug
  10. PAT-013 L1-013. 计算阶乘和
  11. MINA,xSocket同样的性能缺陷及陷阱,Grizzly better
  12. 图像局部特征(八)--斑点检测子SIFT/SURF区别总结
  13. Mac OS X 通过命令行修改ip地址
  14. 苦橙花---不喧哗,自有声
  15. Revit SDK 介绍:CompoundStructure 复合结构
  16. Matlab spline
  17. PDF转CAD在线怎么转换?分享个在线转换的方法
  18. pycharm配置可视化界面流程简介
  19. mysql 数据备份
  20. CNCC2019第三天 | 传统产业如何进行智能化升级?你踩雷了吗?

热门文章

  1. Cadence原理图导出智能PDF(带图页、位号与网络名书签且文本可搜索)
  2. Vivado关联Modelsim进行仿真
  3. 华北理工大学815c语言程序设计,2017年华北理工大学信息工程学院815C程序设计考研冲刺密押题...
  4. 读写配置文件(.ini)
  5. c语言is stack empty,C语言实现栈的问题
  6. tkinter 菜单添加事件_tkinter学习教程(七)
  7. 温州大学计算机与人工智能学院2022年硕士研究生招生复试咨询开始啦!
  8. 【深度学习】PyTorch 中的线性回归和梯度下降
  9. 78万奖金!天池最新CV大赛来了
  10. 还怕GPU资源不够用?多实例GPU MIG助攻资源利用难题