前些天看了一个要上大四的学长写的一篇Android实习生求职经历,了解到一些关于Android的面试题,其中Android的四大组件(Activity、Service服务、Content Provider内容提供者、BroadcastReceiver广播接收器)是最容易出面试题。除了应付面试,四大组件也是Android开发者必须要掌握的。于是Shamoo在网上收集了很多资料,将有用的整理起来。
Activity的介绍
Activity在Android应用中是一个单独的界面,它上面可以显示一些控件也可以监听并处理用户的事件做出响应。
Activity之间是通过Intent进行通信。在Intent 的描述结构中,有两个最重要的部分:动作和动作对应的数据。
典型的动作类型有:MAIN(activity的门户)、VIEW、PICK、EDIT 等。而动作对应的数据则以URI 的形式进行表示。例如:要查看一个人的联系方式,你需要创建一个动作类型为VIEW 的intent,以及一个表示这个人的URI。
与Intent相关的一类是IntentFilter,顾名思义就是意图的过滤器,Activity可以通过IntentFilter响应相关的请求,其他不相关的请求则过滤掉。一个IntentFilter 则用于描述一个activity(或者IntentReceiver)能够操作哪些intent。IntentFilter 需要在AndroidManifest.xml 中定义。通过解析各种Intent,从一个屏幕导航到另一个屏幕是很简单的。当向前导航时,Activity 将会调用startActivity(Intent myIntent)方法。然后,系统会在所有安装的应用程序中定义的IntentFilter 中查找,找到最匹配myIntent 的Intent 对应的activity。新的activity 接收到myIntent 的通知后,开始运行。当startActivity 方法被调用将触发解析myIntent 的动作,这个机制提供了两个关键好处:
A、Activities 能够重复利用从其它组件中以Intent 的形式产生的一个请求;
B、Activities 可以在任何时候被一个具有相同IntentFilter 的新的Activity 取代。
AndroidManifest文件中含有如下过滤器的Activity组件为默认启动类当程序启动时系统自动调用它
<intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter>
AndroidManifest文件中进行注册格式如下:
<activity>元素的name 属性指定了实现了这个activity 的Activity 的子类。icon 和label 属性指向了包含展示给用户的此activity 的图标和标签的资源文件。
Activity的激活
Activity的激活通过传递一个Intent 对象至Context.startActivity()或Activity.startActivityForResult()以载入(或指定新工作给)一个activity。相应的activity 可以通过调用getIntent() 方法来查看激活它的intent。如果它期望它所启动的那个activity 返回一个结果,它会以调用startActivityForResult()来取代startActivity()。比如说,如果它启动了另外一个Activity 以使用户挑选一张照片,它也许想知道哪张照片被选中了。结果将会被封装在一个Intent 对象中,并传递给发出调用的activity 的onActivityResult() 方法。
Activity关闭
可以通过调用它的finish()方法来关闭一个activity
Activity的生命周期
与Activity生命周期相关的就是任务。任务其实就是Activity 的栈它由一个或多个Activity组成的共同完成一个完整的用户体验, 换句话说任务就是” 应用程序” (可以是一个也可以是多个,比如你想让用户看到某个地方的街道地图。而已经存在一个具有此功能的activity 了,那么你的activity 所需要做的工作就是把请求信息放到一个Intent 对象里面,并把它传递给startActivity()。于是屏幕就会显示那个地图。而当用户按下BACK 键的时候,上一个Activity 又会再一次的显示在屏幕上,此时任务是由应用程序中两个的相关Activity组成的)栈底是启动整个任务的Activity,栈顶的是当前运行的用户可以交互的Activity,当一个Activity 启动另外一个的时候,新的activity 就被压入栈,并成为当前运行的Activity。而前一个Activity 仍保持在栈之中。当用户按下BACK 键的时候,当前Activity 出栈,而前一个恢复为当前运行的Activity。栈中保存的其实是对象,栈中的Activity 永远不会重排,只会压入或弹出,所以如果发生了诸如需要多个街道地图显示的情况,就会使得一个任务中出现多个同一Activity 子类的实例同时存在。
任务中的所有Activity 是作为一个整体进行移动的。整个的任务(即activity 栈)可以移到前台,或退至后台。举个例子说,比如当前任务在栈中存有四个Activity──三个在当前Activity 之下。当用户按下HOME 键的时候,回到了应用程序加载器,然后选择了一个新的应用程序(也就是一个新任务)。则当前任务遁入后台,而新任务的根Activity 显示出来。然后,过了一小会儿,用户再次回到了应用程序加载器而又选择了前一个应用程序(上一个任务)。于是那个任务,带着它栈中所有的四个Activity,再一次的到了前台。当用户按下BACK 键的时候,屏幕不会显示出用户刚才离开的Activity(上一个任务的根Activity)。取而代之,当前任务的栈中最上面的Activity 被弹出,而同一任务中的上一个Activity 显示了出来。
Android系统是一个多任务(Multi-Task)的操作系统,可以在用手机听音乐的同时,也执行其他多个程序。每多执行一个应用程序,就会多耗费一些系统内存,当同时执行的程序过多,或是关闭的程序没有正确释放掉内存,系统就会觉得越来越慢,甚至不稳定。
为了解决这个问题, Android 引入了一个新的机制-- 生命周期(Life Cycle)。
Android 应用程序的生命周期是由Android 框架进行管理,而不是由应用程序直接控制。通常,每一个应用程序(入口一般会是一个Activity 的onCreate 方法),都会产生一个进程(Process)。当系统内存即将不足的时候,会依照优先级自动进行进程(process)的回收。不管是使用者或开发者, 都无法确定的应用程序何时会被回收。所以为了很好的防止数据丢失和其他问题,了解生命周期很重要。
Activity生命周期:
Activity整个生命周期的4种状态、7个重要方法和3个嵌套循环
4种状态:
1、活动(Active/Running)状态
当Activity运行在屏幕前台(处于当前任务活动栈的最上面),此时它获取了焦点能响应用户的操作,属于运行状态,同一个时刻只会有一个Activity 处于活动(Active)或运行(Running)状态
2、暂停(Paused)状态
当Activity失去焦点但仍对用户可见(如在它之上有另一个透明的Activity或Toast、AlertDialog等弹出窗口时)它处于暂停状态。暂停的Activity仍然是存活状态(它保留着所有的状态和成员信息并保持和窗口管理器的连接),但是当系统内存极小时可以被系统杀掉
3、停止(Stopped)状态
完全被另一个Activity遮挡时处于停止状态,它仍然保留着所有的状态和成员信息。只是对用户不可见,当其他地方需要内存时它往往被系统杀掉
4、非活动(Dead)状态
Activity 尚未被启动、已经被手动终止,或已经被系统回收时处于非活动的状态,要手动终止Activity,可以在程序中调用"finish"方法。
7个重要方法
当Activity从一种状态进入另一状态时系统会自动调用下面相应的方法来通知用户这种变化当Activity第一次被实例化的时候系统会调用,整个生命周期只调用1次这个方法
通常用于初始化设置: 1、为Activity设置所要使用的布局文件 2、为按钮绑定监听器等静态的设置操作,使用方法onCreate(Bundle savedInstanceState);
当Activity可见未获得用户焦点不能交互时系统会调用onStart();
当Activity已经停止然后重新被启动时系统会调用onRestart();
当Activity可见且获得用户焦点能交互时系统会调用onResume();
当系统启动另外一个新的Activity时,在新Activity启动之前被系统调用保存现有的Activity中的持久数据、停止动画等,这个实现方法必须非常快。当系统而不是用户自己出于回收内存时,关闭了Activity 之后。用户会期望当他再次回到这个activity 的时候,它仍保持着上次离开时的样子。此时用到了onSaveInstanceState(),方法onSaveInstanceState()用来保存Activity被杀之前的状态,在onPause()之前被触发,当系统为了节省内存销毁了Activity(用户本不想销毁)时就需要重写这个方法了,当此Activity再次被实例化时会通过onCreate(Bundle savedInstanceState)将已经保存的临时状态数据传入因为onSaveInstanceState()方法不总是被调用,触发条件为(按下HOME键,按下电源按键关闭屏幕,横竖屏切换情况下),你应该仅重写onSaveInstanceState()来记录Activity的临时状态,而不是持久的数据。应该使用onPause()来存储持久数据。
当Activity被新的Activity完全覆盖不可见时被系统调用onStop();
当Activity(用户调用finish()或系统由于内存不足)被系统销毁杀掉时系统调用onDestroy(),(整个生命周期只调用1次)用来释放onCreate ()方法中创建的资源,如结束线程等。
3个嵌套循环
1、Activity完整的生命周期:从第一次调用onCreate()开始直到调用onDestroy()结束
2、Activity的可视生命周期:从调用onStart()到相应的调用onStop()
在这两个方法之间,可以保持显示Activity所需要的资源。如在onStart()中注册一个广播接收者监听影响你的UI的改变,在onStop() 中注销。
3、Activity的前台生命周期:从调用onResume()到相应的调用onPause()。
举例子:
有3个Acitivity,分别用One,Two(透明的),Three表示,One是应用启动时的主Activity
启动第一个界面Activity One时,它的次序是
onCreate (ONE) - onStart (ONE) - onResume(ONE)
点"打开透明Activity"按钮时,这时走的次序是
onPause(ONE) - onCreate(TWO) - onStart(TWO) - onResume(TWO)
再点back回到第一个界面,Two会被杀这时走的次序是
onPause(TWO) - onActivityResult(ONE) - onResume(ONE) - onStop(TWO) - onDestroy(TWO)
点"打开全屏Activity"按钮时,这时走的次序是
onPause(ONE) - onCreate(Three) - onStart(Three) - onResume(Three) - onStop(ONE)
再点back回到第一个界面,Three会被杀这时走的次序是
onPause(Three) - onActivityResult(ONE) - onRestart(ONE) - onStart(ONE)- onResume(ONE) - onStop(Three) - onDestroy(Three)
<补充>如果按HOME将程序挂到后台,次序是
onSaveInstanceState()-onPause(ONE)-onStop(ONE)
<补充>从后台返回,次序是
onRestart(ONE)-onStart(ONE) - onResume(ONE)
再点back退出应用时,它的次序是
onPause(ONE) - onStop(ONE) - onDestroy(ONE)