一、什么是activity
Activity 是用户接口程序,原则上它会提供给用户一个交互式的接口功能。它是 android 应用程序的基本功能单元。Activity 本身是没有界面的。所以activity类创建了一个窗口,开发人员可以通过setContentView(View)接口把UI放到activity创建的窗口上,当activity指向全屏窗口时,也可以用其他方式实现:作为漂浮窗口(通过windowIsFloating的主题集合),或者嵌入到其他的activity(使用ActivityGroup)。activity是单独的,用于处理用户操作。几乎所有的activity都要和用户打交道,
【Activity】
一个Activity是一个应用程序组件,提供一个屏幕,用户可以用来交互为了完成某项任务,例如拨号、拍照、发送email、看地图。每一个activity被给予一个窗口,在上面可以绘制用户接口。窗口通常充满屏幕,但也可以小于屏幕而浮于其它窗口之上。
一个应用程序通常由多个activities组成,他们通常是松耦合关系。通常,一个应用程序中的activity被指定为"main"activity,当第一次启动应用程序的时候呈现给用户的那个activity。每一个activity然后可以启动另一个activity为了完成不同的动作。每一次一个activity启动,前一个activity就停止了,但是系统保留activity在一个栈上(“back stack”)。当一个新activity启动,它被推送到栈顶,取得用户焦点。Back Stack符合简单“后进先出”原则,所以,当用户完成当前activity然后点击back按钮,它被弹出栈(并且被摧毁),然后之前的activity恢复。
当一个activity因新的activity启动而停止,它被通知这种状态转变通过activity的生命周期回调函数。有许多回调函数一个activity可能会收到,源于它自己的状态变化-无论系统创建它、停止它、恢复它、摧毁它-并且每个回调提供你完成适合这个状态的指定工作的机会。例如,当停止的时候,你的activity应该释放任何大的对象,例如网络数据库连接。当activity恢复,你可以重新获得必要的资源和恢复被中断的动作。这些状态转换都是activity的生命周期的部分。
【Creating an Activity】
创建一个activity,你必须创建一个Activity的子类(或者一个Activity的子类的子类)。在你的子类中,你需要实现系统回调的回调方法,当activity在它的生命周期的多种状态中转换的时候,例如当activity被创建、停止、恢复或摧毁。两个最重要的回调方法是:
onCreate()
你必须实现这个方法。系统调用它当创建你的activity的时候。在你的实现中,你应该初始化你的activity的基本的组件。更重要的是,这里就是你必须调用setContentView()来定义activity用户接口而已的地方。onPause()
系统调用这个方法当用户离开你的activity(虽然不总是意味着activity被摧毁)。这通常是你应该提交任何变化,那此将会超越user session而存在的(因为用户可能不再回来)。
有若干其它生命周期回调函数你应该使用为了提供一个流畅的用户体验,并表操作异常中断会引起你的activity被中断甚至被摧毁。
1、Implementing a user interface
一个activity的用户接口被一个层次化的视图提供--继承于View类的对象。每个View控制activity窗口中的一个特定矩形区域并且能响应用户交互。例如,一个view可能是个button,初始化动作当用户触摸它的时候。
Android提供大量预定义的view,你可以使用来设计和组件你的布局。“Widgets”是一种给屏幕提供可视化(并且交互)元素的view,例如按钮、文件域、复选框或者仅仅是图像。“Layouts”是继承于ViewGroup的View,提供特殊的布局模型为它的子view,例如线程布局、格子布局或相关性布局。你可以子类化View和ViewGroup类(或者存在的子类)来创建自己的widget和而已并且应用它们到你的activity布局中。
最普通的方法是定义一个布局使用view加上XML布局文件保存在你的程序资源里。这样,你可以单独维护你的用户接口设计,而与定义activity行为的代码无关。你可以设置布局作为UI使用setContentView(),传递资源布局的资源ID。可是,你也可以创建新Views在你的activity代码,并且创建一个view层次通过插入新Views到ViewGroup,然后使用那个布局通过传递到根ViewGroup给setContentView()。
【Declaring the activity in the manifest】
你必须声明你的activity在manifest文件为了它可以被系统访问。要声明你的activity,打开你的manifest文件,添加一个<activity>元素作为<application>元素的子元素。例如:
【Using intent filters】
一个<activity>元素也能指定多种intent filters--使用<inetent-filter>元素--为了声明其它应用程序可以激活它。
当你创建一个新应用程序使用Android SDK工具,存根activity自动为你创建,包含一个intent filter,声明了activity响应"main"动作,并且应该被 放置 在"launcher"分类。Intent filter看起来像这个样子。
<action>元素指定这是一个"main"入口点对这个应用程序。<category>元素指定,这个activity应该被列入系统应用程序列表中(为了允许用户启动这个activity)。
如果你希望应用程序自包含,并且不希望别的应用程序激活它的activities,那么你不需要任何其它intent filters。只有一个activity应该有“main"动作和”launcher“分类,就像前面这个例子。你不希望被其它应用程序访问原Activities应该没有intent filters而且你能启动他们通过自己显示的intent。
可是,如果你希望你的activity响应影含的intents,从其它应用程序(和你自己的),那么你必须定义额外的intent filters为这个activity。每一种你希望响应的类型的intent,你必须包含<intent-filter>,包含<action>元素,可选的,一个<category>元素并且/或一个<data>元素。这些元素指定你的activity能响应的intent的类型。
【Starting an Activity】
你可以开启另一个activity通过startActivity(),传递一个Intent描述了你希望启动的Activity。Intent指定要么准备的activity你希望启动或描述你希望完成的动作(操作系统选择合适的activity为你,可能来自定不同的应用程序)。一个intent可以传输小量数据被启动的activity使用。
完全工作在你的应用程序之内,你将经常需要简单的启动一个未知的activity。你可以这么通过创建一个intent显示的定义你希望启动的activity,使用类名。例如,下面显示一个activity怎么启动另一个activity命名为SignInActivity:
可是,你的应用程序或许希望执行一些动作,例如发送一份邮件、文件消息或者状态更新,使用你的activity的数据。在这种情况下,你的应用程序或许没有它自己的activity来完成这个动作,因此你可以促使设备上其它应用程序提供的activity来完成你的动作。这才是intent真正有价值的地方--你可以创建一个intent描述一个你希望执行的动作,然后系统启动一个合适的activity从其它应用程序。如果有多种activities可以处理这个intent,那么 用户可以选择哪一个来执行。例如,如果你希望允许用户发送邮件,你可以创建下面的Intent:
EXTRA_EMAIL额外的添加给intent一个字符串数组指定email地址,当一个邮件应用程序响应这个intent的时候,它读取这些字符串数组并且放置他们到相应字段。在这种情况下,email应用程序的activity启动并且当用户执行完,你的activity恢复。
【Starting an activity for a result】
有时,你或许希望接收一个结果从你启动的activity。在这种情况下,开启这个activity通过startActivityForResult()(而不是startActivity())。然后从随后的activity接收结果,实现onActiviryResult()回调函数。当随后的activity完成,它返回一个结果给你的onActivityResult()函数通过一个intent。
例如,或许你希望用户选择他们中的一个联系人,所以你的activity可以对这个联系人做些事情。下面是你怎么建立这样一个Intent和操作结果:
这个例子展现了基本的逻辑你应该使用的在你的onActivityResult()函数中,为了操作一个activity的结果。第一个条件检测是否请求成功--如果是,那么 resultCode将会是RESULT_OK--并且是否这个请求是否是这个响应是响知道--在这种情况下,requestCode匹配第二个参数用startActivityForResult()的参数。在那里,代码操作activity结果通过查询返回在intent中的数据(data参数)。
将发生的是,一个ContentResolver实现查询content provider,返回一个Cursor允许读查询的数据。
【Shut Down an Activity】
你可以关闭一个activity通过调用自身的finish()方法。你也可以关闭一个独立的activity你之前启动的通过finiActivity()。
注意:在大多数情况下,你不应该显示结果一个activity使用这些方法。正在下文所讨论的关于activity的生命周期,Android系统管理一个activity的生命周期为你,所以你不需要结果你自己的activity。调用这些函数对用户体验有害并且只有在你决对不希望用户返回到这个activity的情况下。
二、activity生命周期
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 -> onStart -> onResume;在Activity被kill掉的时候方法顺序是onPause -> onStop -> onDestroy,此为一个完整的Lifecycle。那么对于中断处理(比如电话来了),则是onPause -> onStop,恢复时onStart -> onResume;如果当前应用程序的是一个Theme为Translucent(半透明) 或者Dialog 的Activity那么中断就是onPause ,恢复的时候onResume。
那么对于”Other app need memory”,就是我们手机在运行一个应用程序的时候,有可能打进来电话发进来短信,或者没有电了,这时候程序都会被中断,优先去服务电话的基本功能,另外系统也不允许你占用太多资源,至少要保证一些功能(比如电话),所以资源不足的时候也就有可能被kill掉。
方法在系统中的作用及我们应该做什么:
onCreate:在这里创建界面,做一些数据的初始化工作;
onStart: 到这一步变成“用户可见不可交互”的状态;
onResume:变成和用户可交互的,(在Activity栈系统通过栈的方式管理这些Activity,即当前Activity在栈的最上端,运行完弹出栈,则回到上一个Activity);
onPause:到这一步是可见但不可交互的,系统会停止动画等消耗CPU的事情。从上文的描述已经知道,应该在这里保存你的一些数据,因为这个时候你的程序的优先级降 低,有可能被系统收回。在这里保存的数据,应该在onResume里读出来。
onStop:变得不可见 ,被下一个activity覆盖了
onDestroy:这是Activity被kill前最后一个被调用方法了,可能是其他类调用finish方法或者是系统为了节省空间将它暂时性的干掉,可以用isFinishing()来判断它,如果你有 一个Progress Dialog在线程中运行,请在onDestroy里把他cancel掉,不然等线程结束的时候,调用Dialog的cancel方法会抛异常。
onPause,onstop, onDestroy,三种状态下 activity都有可能被系统kill 掉。
三、Activity之间的通信
在 Android 中,不同的 Activity 实例可能运行在一个进程中,也可能运行在不同的进程中。因此我们需要一种特别的机制帮助我们在 Activity 之间传递消息。Android 中通过 Intent 对象来表示一条消息,一个 Intent 对象不仅包含有这个消息的目的地,还可以包含消息的内容,这好比一封 Email,其中不仅应该包含收件地址,还可以包含具体的内容。对于一个 Intent 对象,消息“目的地”是必须的,而内容则是可选项。
Intent负责对操作的动作、动作涉及数据、附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将 Intent传递给调用的组件,并完成组件的调用。因此,Intent在这里起着一个媒体中介的作用,专门提供组件互相调用的相关信息,实现调用者与被调用者之间的解耦。
在应用中,我们可以以两种形式来使用Intent:
直接Intent:指定了component属性的Intent(调用setComponent(ComponentName)或者setClass(Context, Class)来指定)。通过指定具体的组件类,通知应用启动对应的组件。
间接Intent:没有指定comonent属性的Intent。这些Intent需要包含足够的信息,这样系统才能根据这些信息,在在所有的可用组件中,确定满足此Intent的组件。
对于直接Intent,Android不需要去做解析,因为目标组件已经很明确。
Android需要解析的是那些间接Intent,通过解析,将 Intent映射给可以处理此Intent的Activity、IntentReceiver或Service。Intent解析机制主要是通过查找已注册在AndroidManifest.xml中的所有IntentFilter及其中定义的Intent,最终找到匹配的Intent。
四、Activity 的 Intent Filter
Intent Filter 描述了一个组件愿意接收什么样的 Intent 对象,Android 将其抽象为 android.content.IntentFilter 类。在 Android 的 AndroidManifest.xml 配置文件中可以通过 <intent-filter >节点为一个 Activity 指定其 Intent Filter,以便告诉系统该 Activity 可以响应什么类型的 Intent。
当使用 startActivity(intent) 来启动另外一个 Activity 时,如果直接指定 intent 对象的 Component 属性,那么 Activity Manager 将试图启动其 Component 属性指定的 Activity。否则 Android 将通过 Intent 的其它属性从安装在系统中的所有 Activity 中查找与之最匹配的一个启动,如果没有找到合适的 Activity,应用程序会得到一个系统抛出的异常。这个匹配的过程如下:
五、Activity的栈式管理
Android针对Activity的管理使用的是栈,就是说某一个时刻只有一个Activity处在栈顶,当这个Activity被销毁后,下面的Activity才有可能浮到栈顶,或者有一个新的Activity被创建出来,则旧的Activity就被压栈沉下去了。Activity是Android程序的表现层。程序的每一个显示屏幕就是一个Activity。正在运行的Activity处在栈的最顶端,它是运行状态的。
当在程序中调用 Activity.finish()方法时,结果和用户按下 BACK 键一样:它告诉 Activity Manager该Activity实例可以被“回收”。随后 Activity Manager 激活处于栈第二层的 Activity ,把原 Activity 压入到栈的第二层,从 Running 状态转到 Paused 状态。
六、Activity的加载模式
standard、singleTop、singleTask、singleInstance(其中前两个是一组、后两个是一组),默认为standard
standard:就是intent将发送给新的实例,所以每次跳转都会生成新的activity。
singleTop:也是发送新的实例,但不同standard的一点是,在请求的Activity正好位于栈顶时(配置成singleTop的Activity),不会构造新的实例
singleTask:和后面的singleInstance都只创建一个实例,当intent到来,需要创建设置为singleTask的Activity的时候,系统会检查栈里面是否已经有该Activity的实例。如果有直接将intent发送给它。
singleInstance:
首先说明一下task这个概念,Task可以认为是一个栈,可放入多个Activity。比如启动一个应用,那么Android就创建了一个Task,然后启动这个应用的入口Activity,那在它的界面上调用其他的Activity也只是在这个task里面。那如果在多个task中共享一个Activity的话怎么办呢。举个例来说,如果开启一个导游服务类的应用程序,里面有个Activity是开启GOOGLE地图的,当按下home键退回到主菜单又启动GOOGLE地图的应用时,显示的就是刚才的地图,实际上是同一个Activity,实际上这就引入了singleInstance。singleInstance模式就是将该Activity单独放入一个栈中,这样这个栈中只有这一个Activity,不同应用的intent都由这个Activity接收和展示,这样就做到了共享。当然前提是这些应用都没有被销毁,所以刚才是按下的HOME键,如果按下了返回键,则无效。
七、Activity的跳转
Activity跳转,无返回结果
Activity跳转,返回数据/结果