AT-Activity
关于Activity的粗略翻译
原地址:Activity
类概述:
Activity是独立的、突出的可被用户操作的东西。几乎所有的Activity都是与用户进行交互的,所以这些Activity会很小心的帮我们创建一个窗体(Window),而在这个窗体中,你可以通过调用 setContentView(View) 来设置你自己的界面(UI)。虽然Activities经常被用来作为全屏(full-screen)展示给用户,但是它们不仅可以这样,它们还可以用在其它方面:作为一个浮动的窗体来使用(通过在主题中设置 windowIsFloating 属性来实现),你还可以将一个Activity镶嵌在另一个Activity中(通过使用 ActivityGroup)。而在我们继承Activity时,几乎都会实现下面两种方法:
- onCreate(Bundle) :该方法就是用来初始化你的Activity的。然而更重要的是,在这个方法里面,通常会调用 setContentView(int) 方法,传入的参数就是一个你自己定义的布局资源文件(layout resource),然后使用 findViewById(int) 方法来在你刚刚设置的那个布局文件中查找对应的你需要的控件。
- onPasue(): 在该方法中你可以处理一些当用户离开当Activity后的操作。然而更重要的是,用户所进行的操作导致的新的数据变化都应该在这个方法中来保存。
为了在使用 Context.startActivity()方法能正常找到对应的Activity,所以所有的Activity都应该在对应包下的 AndroidManifest.xml 文件中通过使用 <activity>标签来定义。
Activity生命周期
Activity在系统中是通过Activity栈来管理的。当一个新的Activity开始时,这个新启动的Activity将会被放在栈的顶部,同时该Activity将会运行起来,而前一个Activity将会在当前Activity的下面(栈下面),并且在当前Activity退出前台之前,前一个不会出现在前台的。
本质上来说, 一个Activity中会有下面四种状态:
- 如果一个Activity在屏幕前台的话,便是运行状态。
- 如果一个Activity失去焦点但是仍可见(也就是说此时有一个非全屏的Activity弹出了,或者一个透明的Activity在前台),此时对应Activity就会处于暂停状态(paused)。此时Activity尽管是暂停状态,当它仍然是具有"活力的"(具有活力也就是说会保持所有的状态、记住对应信息,并且和Window Manager一直是还是绑定(attach)状态的),但是尽管是这样,它毕竟是暂停的,如果此时系统内存空间严重不足的时候还是会把暂停的这个Activity“杀掉”的。
- 如果一个Activity被另一Activity完全挡住时,它将会停止(stopped)。但是此时仍然会保持所有之前的状态、记住用户信息。然而,因为它不可见了嘛,所以与它对应的的窗体(window)便会隐藏,并且经常会在系统需要时被系统"杀掉"。
- 如果一个Activity处于暂停(paused)或者停止(stopped)状态时,系统会不加询问的从内存中终止该Activity,或者“杀掉”对应的进程。当该Activity将被再次显示到前台给用户时,该Activity必须重新启动并且完全恢复之前的状态。
下面的图解展示了一个Activity的一些重要状态的转换路径。其中矩形代表当Activity状态变化时的一些回调方法,你可以实现这些回调方法来执行一些操作。其中有色的椭圆是Activity当前的的主要状态。
下面将会介绍三种在Activity中你可能会感兴趣的主要的循环
- 在Activity中发生的全部的生命周期循环,这个循环过程是发生在 onCreate(Bundle)方法到最后的onDestroy()方法之间。一个Activity将在 onCreate(Bundle) 中来设置、初始化一些东西,然后最后在onDestroy()释放所有之前的资源,比如现在你有一个需求就是创建一个线程在后台工作,用来执行从网上下载数据的工作,这样的话你可以在 onCreate() 中来初始化创建这个线程,最后在 onDestroy() 中来停止这个线程。
- 可见的生命周期循环,这个循环过程是发生在 onStart() 方法到 onStop() 方法之间。在这段时间内,用户在屏幕上是可以看见这个Activity的,尽管有可能没有在前台与用户进行交互。在这两个方法中,你可以保持(我感觉应该是翻译成 初始化创建 会更好点)以那些用来给用户展示的资源。比如你可以在 onStart() 中注册一个 广播接收器 (BroadcastReceiver)来监听那些对界面产生影响的那些变化,然后在当用户不再能看到的界面时,即在 onStop() 中解除注册(unRegister)。值得注意的是, onStart()和onStop()方法可以被调用好多次,因为只要当Activity显示给用户和对用户隐藏而使用户看不到时就会调用这两个方法,明显在一个应用中这样的场景会多次发生的。
- 前台生命周期循环,这个循环发生在 onResume() 和 onPause() 方法之间。在这段时间内,当前Activity会在所有其他Activity的前面并且与用户进行交互。一个Activity可以频繁地调用这两个方法来恢复Activity和暂停Activity。比如当你的设备息屏开始休眠时,当一个Activity的结果送达时,当一个新的Intent到达时....因此在你重写实现了这两个方法时不应该再里面放掏过耗时的工作,而应该是一些"轻量级"的。
整个的Activity生命周期是通过下面代码中的方式来定义的。所有的这些方法都是hooks(原谅我不知道怎么把它翻译到这句中去 (∩_∩) ),你可以重写对应需要的方法,以实现在Activity状态变化时执行对应的、恰当的工作的目的。所有的Activities都将实现 onCreate(Buldle) 方法来初始化,有些也实现了 onPause() 方法来提交一些变化的数据,或者做一些准备工作来以停止和用户的交互。你应该在实现这些方法时记得调用一下父类的对应方法。
public class Activity extends ApplicationContext {
protected void onCreate(Bundle savedInstanceState); protected void onStart(); protected void onRestart(); protected void onResume(); protected void onPause(); protected void onStop(); protected void onDestroy();
}
通常情况下,在Activity生命周期的转变会类似于下面的方法顺序和介绍。
方法 | 描述 | 是否可以被系统杀掉? | 下一步执行 |
onCreate() | 当Activity第一次创建时会调用该方法,在该方法中,你应该做好全部的初始化设置工作:创建视图(View),绑定数据, 比如List的数据绑定。该方法还给我们提供了一个Bundle对象,这个Bundle中包括了上一次的状态信息,前提是上一次有储存数据到Bundle中。在该方法之后,经常会执行 onStart()。 | 不可以 | onStart() |
onRestart() | 当你当前的的Activity被停止(stopped)了,前一个Activity要重新启动了,此时会调用本方法。在此方法执行之后,通常会执行 onStart() 方法 | 不可以 | onStart() |
onStart() | 当Activity对于用户来说变得可见时,会调用该方法。如果Activity转到前台来显示时会紧跟着调用 onResume() 方法,如果它离开前台而被隐藏时会调用 onStop() (PS:感觉这里有问题,onStart()怎么能接着直接执行到的onStop()呢?) | 不可以 |
onResume() 或者onStop() |
onResume() | 当Activity开始和用户产生交互时会调用该方法。在此时,该Activity已经在Activity栈的顶部了,开始可以处理来自用户的交互了。该方法后一般会执行 onPause() | 不可以 | onPause() |
onPasue() | 当系统准备将要启动前一个Activity时,会调用本方法。在本方法中,典型的做法就是在本方法中提交保存那些未保存的数据变化、停止动画、还有其他之类的,只要是坑了消耗占用CPU的都应该在本方法中停掉。在实现本方法时要注意:实现后的方法中不能有太过耗时的操作,应该越快越好,因为下一个Activity会在等着本方法返回(return)后才会恢复(resume)。在本方法执行完成后,如果本Activity又被返回到了前台,那么此时会跟着执行 onResume(),而如果在本方法之后,该Activity变得不可见了,那么紧跟着就会执行 onStop()方法 |
onResume() 或者onStop() |
|
onStop() | 当Activity对于用户不再可见时,会调用本方法,因为此时另一个Activity已经恢复(resumed)到哦了前台,挡住了本Activity。当另一个新的Activity启动(started)时、一个先前存在了的Activity再次返回到前台时、或者当前Activity被销毁时,以上三种情景都会调用本方法。在本方法执行之后,如果当前Activity又转到前台显示了,就会调用 onRestart(),如果当前Activity不再可见就会调用 onDestroy()方法销毁掉当前的Activity | 可以 | onRestart() 或者 onDestroy() |
onDestroy() | 在你的Activity被销毁之前调用的最后一个方法就是本方法。调用该方法是因为类Activity正在被结束(finishing)(有时是因为有的人调用了finish(),或者是因为系统临时的销毁掉了这个Activity的实例以用来保存空间。你可以尝试区分 isFinishing() finish() onDestroy()这几种方法) | 可以 | 后面没啦 |
注意上面那个第三列的可被系统"杀掉"的那一列-----其中有些方法是被标记成可以被系统杀掉的,在这些方法返回后,掌握着当前Activity的进程(Process)也许会被系统在任何需要的时候杀掉,尽管你没有在你的代码中通知系统当前可以杀掉。正是因为这样,你应该在 onPause() 方法中将一些应该持续保存的数据(比如用户的输入)保存到存储单元中去。另外, onSaveInstanceState(Bundle) 是在放置Activity到前台调用的(测试onSaveInstanceState()是在onPasue() 之后,在onStop()之前调用的 ),所以在onSaveInstanceState()中你可以任何非实例状态的东西存储到给定的Bundle中来保存起来,然后在之后的 onCreate(Bundle) 中来接收到上次储存了信息的Bundle,如果你需要的话,可以的话使用这个Bundle 来重新创建(恢复)上一个Activity的状态。你可以看一下 进程的生命周期 部分以获取和当前Activity有关的那个进程的更多信息。注意,你最好在 onPause() 中来保存信息,而不知在 onSaveInstanceState()中,因为后者不是生命周期循环中的方法,所以并不能保证在每个这种类似场景中都会调用它(比如在onPause()方法之后就立马被系统杀掉了,此时就没有执行到onSaveInstanceState()方法)。
你应该知道的是在 HONEYCOMB 版本之前,这些语义会有一些变化和不同。从 HONEYCOMB 版本开始到之后,生命周期中,在onStop()方法返回之前,系统是不会杀掉对应的Activity的,这就对上面讲到的onSaveInstanceState()来储存数据有点影响了(也就是说该方法将会在 onPause() 和 onStop() 之间安全可靠的调用)
而对于其它没有被标记为可被杀掉的方法来说,对应的Activity的进程 在方法被调用一直到方法返回后,都是一直保持执行状态的。因此一个Activity处于一个可被杀掉的状态,比如在 onPause() 和 onResume()之间时。
参数变化(Configuration Changes)
如果设备的参数(在 Resources.Configuration 类中定义的参数)发生变化时,设备的所有显示都需要发生变化来适应当前的参数变化。因为Activity是用来作为主要的用来和用户交互的,它包括了对于设备参数变化的支持。
除非你特别定义,否则的话,当设备参数发生变化(比如屏幕方向发生变化,语言发生变化,输入设备发生变化等等),这些变化将会导致当前的Activity被销毁(Destroyed),而这个过程是通过正常的生命周期来形成的,即 onPause() 然后到 onStop(),最后执行到 onDestroy() 。 如果对应的Activity现在在前台正在显示的话,一旦 onDestroy() 被调用之后,后面就会紧跟着又创建一个新的实例来显示,新创建时会从 onSaveInstanceState()中读取上一次保存的实例来恢复。
这样做的原因是任何应用的资源,包括布局文件,都应该根据参数的变化来变化。因此,唯一安全可靠的方式就是重新恢复原先所有的资源,包括布局文件、图片资源以及字符串资源等等。因为Activity必须事先要知道怎样保存它们原先的状态,并且要知道怎样去重新创建这些,因此简单方便的方法就是在新的参数环境下重新启动Activity。
在一些特殊性情况下,我们不想在某些参数发生变化时区重新创建启动Activity。要达到这样的目的的话,你可以在 AndroidManifest文件中通过 android:configChanges 属性来实现。在Manifest文件中声明的哪些参数后,在这些参数发生变化时系统就不会去重新创建Activity了,而是会去调用 onConfigurationChanged(Configuration)方法。相反的,如果有个参数你没有在Manifest文件中去使用 android:configChanges 属性来声明的话,那么当该参数发生变化时,Activity就会发生重建,而不是去调用onConfigurationChanged(Configuration)方法
启动Activities和获得返回结果(Starting Activities and Getting Results)
startActivity(Intent)方法就是用来启动一个新的Activity的,这个新启动的Activity就会处于Activity栈的顶部。该方法只需要一个参数传入,即 Intent ,这个参数中描述了将要被执行的那个Activity。
有些时候,你想要当一个Activity结束时,能够"通知"你一下,告诉你“我已经结束了哦”。比如,你可能会启动另一个Activity用来让用户从通讯录中选择一个人的名片,当选择完成后后,应该将选择的结果返回给“我”。为了实现这样的效果,我们可以使用startActivityForResult(Intent,int)方法来实现,其中第二个整形参数是用来标记区分当前的方法调用。最后返回过来的结果是在 onActivityResult(int,int,Intent)方法中的。
当那个被启动的Activity启动了后,可以在它里面通过调用 setResult(int) 方法来返回数据到启动它的那个Activity中去(即它的父Activity)。然后,它通常需要应用一个返回码,可以是标准的返回码比如 RESULT_CANCELED,RESULT_OK,或者是一些自定义的返回码。另外,如果有需要的话你可以的返回一个包含了数据的Intent对象到启动它的Activity中去。所有的数据信息都会出现在启动它的那个Activity的onActivityResult()方法,连同它刚开始时传入的那些标记码。
如果被启动的Activity由于一些不可抗因素导致中途失败了(比如直接崩溃了),对应的启动它的那个Activity将会收到 RESULT_CANCELED 结果码。
public class MyActivity extends Activity {
... static final int PICK_CONTACT_REQUEST = 0; public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
// When the user center presses, let them pick a contact.
startActivityForResult(
new Intent(Intent.ACTION_PICK,
new Uri("content://contacts")),
PICK_CONTACT_REQUEST);
return true;
}
return false;
} protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
if (requestCode == PICK_CONTACT_REQUEST) {
if (resultCode == RESULT_OK) {
// A contact was picked. Here we will just display it
// to the user.
startActivity(new Intent(Intent.ACTION_VIEW, data));
}
}
}
}
持久保存状态(Saving Persistent State)
后面待续...
AT-Activity的更多相关文章
- EventBus实现activity跟fragment交互数据
最近老是听到技术群里面有人提出需求,activity跟fragment交互数据,或者从一个activity跳转到另外一个activity的fragment,所以我给大家介绍一个开源项目,EventBu ...
- Android—Service与Activity的交互
service-Android的四大组件之一.人称"后台服务"指其本身的运行并不依赖于用户可视的UI界面 实际开发中我们经常需要service和activity之间可以相互传递数据 ...
- Android:Activity+Fragment及它们之间的数据交换.
Android:Activity+Fragment及它们之间的数据交换 关于Fragment与Fragment.Activity通信的四种方式 比较好一点的Activity+Fragment及它们之间 ...
- Android中Activity处理返回结果的实现方式
大家在网上购物时都有这样一个体验,在确认订单选择收货人以及地址时,会跳转页面到我们存入网站内的所有收货信息(包含收货地址,收货人)的界面供我们选择,一旦我们点击其中某一条信息,则会自动跳转到订单提交界 ...
- 报错:You need to use a Theme.AppCompat theme (or descendant) with this activity.
学习 Activity 生命周期时希望通过 Dialog 主题测试 onPause() 和 onStop() 的区别,点击按钮跳转 Activity 时报错: E/AndroidRuntime: FA ...
- Android 旋转屏幕--处理Activity与AsyncTask的最佳解决方案
一.概述 运行时变更就是设备在运行时发生变化(例如屏幕旋转.键盘可用性及语言).发生这些变化,Android会重启Activity,这时就需要保存activity的状态及与activity相关的任务, ...
- Activity之概览屏幕(Overview Screen)
概览屏幕 概览屏幕(也称为最新动态屏幕.最近任务列表或最近使用的应用)是一个系统级别 UI,其中列出了最近访问过的 Activity 和任务. 用户可以浏览该列表并选择要恢复的任务,也可以通过滑动清除 ...
- Android开发学习—— 创建项目时,不是继承activity,而是继承ActionBarActivity
对于我们新建android项目时, 会 继承ActionBarActivity. 我们在新建项目时, 最小需求的sdk 选择 4.0以上版本.这样 新建的android项目就是继承activity了!
- Android中Fragment与Activity之间的交互(两种实现方式)
(未给Fragment的布局设置BackGound) 之前关于Android中Fragment的概念以及创建方式,我专门写了一篇博文<Android中Fragment的两种创建方式>,就如 ...
- Android中Activity的四大启动模式实验简述
作为Android四大组件之一,Activity可以说是最基本也是最常见的组件,它提供了一个显示界面,从而实现与用户的交互,作为初学者,必须熟练掌握.今天我们就来通过实验演示,来帮助大家理解Activ ...
随机推荐
- 【转】为什么C++编译器不能支持对模板的分离式编译
出处:刘未鹏(pongba) http://blog.csdn.net/pongba) 首先,一个编译单元(translation unit)是指一个.cpp文件以及它所#include的所有.h ...
- error C2065:未声明的标识符错误
原文地址:http://blog.sina.com.cn/s/blog_8216ada701017evx.html 在VS2010下进行VC++调试时,出现这样一种错误:error C2065:未声明 ...
- Leetcode OJ : Evaluate Reverse Polish Notation Stack C++ solution
#define ADDITION '+' #define SUBSTRACTION '-' #define MULTIPLICATION '*' #define DIVISION '/' class ...
- CentOS安装nvidia显卡驱动
1.下载 nvidia 相应的驱动: 2.修改/etc/modprobe.d/blacklist.conf文件,在里面加入blacklist nouveau. 3.重建image $ mv /boot ...
- C++ 虚函数表与内存模型
1.虚函数 虚函数是c++实现多态的有力武器,声明虚函数只需在函数前加上virtual关键字,虚函数的定义不用加virtual关键字. 2.虚函数要点 (1) 静态成员函数不能声明为虚函数 可以这么理 ...
- JSF2.0 タグ一覧 (h:panelGrid) 編
JSF の HTML (UIComponent) 系タグにはテーブルを作成するタグが2種類用意されています.これらのタグと固有機能系タグを組み合わせることでテーブルを使用した画面を作成可能です. 6. ...
- 基于野火M3开发板(STM32F103VET6)的迷宫小球(重力感应控制)游戏开发
2013-03-03 这是研一上学期<实时嵌入式系统实验>课程的大作业,是利用野火板的资源,加上一个AHRS(Attitude and Heading Reference System,姿 ...
- CentOS无损调整home,root磁盘的大小
调整硬盘分区大小想增加root空间,减少home空间. 需要说明的是整个操作需要使用root用户. 1.查看硬盘使用情况. [root@Slave1 /]# df -h Filesystem Size ...
- Thinking in Java
今天无意中看到了这本书(Thinking in Java)的中关于多态的一段描述,瞬间就感觉到了多态原来是这样的.
- Android Binder------ServiceManager启动分析
ServiceManager启动分析 简述: ServiceManager是一个全局的manager.调用了Jni函数,实现addServicew getService checkService ...