第4章 Andorid活动与意图 (Activity与Intent) QQ号:1281147324 QQ群:489059718(Android编程-清华版) 287966120(公共版) 网络资源:http://www.xs360.cn/book
主要内容
主要内容
主要内容
4.1 Activity详解 Activity是Android的一种应用程序组件,该组件为用户提供了一 个屏幕,一个Activity通常就是一个单独的屏幕,它上面可以显示一 些控件也可以监听并处理用户的事件做出响应,如打电话、拍照 Android中主要包含四大组件:Activity、Service、 BroadcastReceiver、ContentProvider。其中Activity是最基础也是 最常见的组件。 Activity负责与用户交互,该组件提供了一个显示用户界面的屏幕, 用户通过与这个屏幕交互可完成一定的功能 每一个Activity都提供了一个可视化的用户界面。通过 setContentView()方法来设定界面显示内容。这个界面通常是充满整 个屏幕,但可通过设置使这个屏幕更小或者是漂浮在其他界面窗口之 上。
4.1.1 Activity概述 一个应用程序通常由多个彼此之间松耦合的Activity组成。通常,有一个Activity被指定为主Activity。当应用程序第一次启动的时候,该Activity会显示给用户。 每个Activity都可以启动其他Activity用于执行不同的动作(功能)。当一个新的Activity启动的时候,先前的那个Activity就会停止,但是系统会在堆栈中保存该Activity。 堆栈遵循后进先出的队列原则,因此,当用户使用完当前的Activity并按Back键时,该Activity将从堆栈中取出(并销毁,释放内存空间),然后先前的Activity恢复并获取焦点。
4.1.2 创建和配置Activity 创建Activity的需具备条件 (1)创建Activity需要继承Activity基类或其子类, 如 MyActivity exand ListActivity或TabActivity。 (2)创建Activity需要实现一个或多个方法; 其中最常见的就是onCreate(Bundle status)方法,该方法将会 在Activity创建时被回调,并可调用setContentView(View view) 方法来显示要展示的View。 当用户离开Activity时,系统将会自动调用onPause()方法,但这 并不意味这该Activity被销毁了。在该方法中,应该实现一些需要持 久化的功能,因为用户可能不会再返回该Activity,该进程可能会被 杀死。 注:Android应用要求四大组件都必须先进行注册。
Activity状态(创建)发生改变会调用该回调方法 public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.test_scrollvitew); } public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; Activity状态(创建)发生改变会调用该回调方法
4.1.2 创建和配置Activity 为<application …/>元素添加<activity…/>子元素即可注册Activity。注册时,主要有以下几个属性: name:指定该Activity的实现类的类名; icon:指定该Activity对应的图标; label:指定该Activity的标签。 配置Activity时通常还可以指定一个或多个<intent-filter…/>元素,该元素用于指定该Activity可响应的Intent。 上述配置中,只有name属性是必须的,而其它属性或标签元素都是可选的(演示-解释name不同)。
决定最先运行的launcher中那个activity,该属性会最先调用 <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="cn.example.srcandbackground.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> Activity对应的类名 标题显示文字 配置Activity过滤条件 设置为主Activity 设置Activity的附加信息 决定最先运行的launcher中那个activity,该属性会最先调用
4.1.3 启动和关闭Activity 一个Android应用通常只有一个Activity会作为程序的入口。而应用中的其他Activity,通常都由入口Activity启动,或由入口Activity启动的Activity启动。 Activity启动其他Activity的方法如下: startActivity(Intent intent):启动其他Activity; startActivityForResult(Intent intent,int requestCode):程序将会得到新启动Activity的结果(通过重写onActivityResult(…)方法来获取),requestCode参数代表启动Activity的请求码。这个请求码的值由开发者根据业务自行设置,用于标识请求来源。 查看activity相关帮助文档
4.1.3 启动和关闭Activity 上面两个方法,都需要传入一个Intent类型的参数,该参数是对你所需要启动的Activity的描述,既可以是一个确切的Activity类,也可以是所需要启动的Activity的一些特征,然后由系统查找符合该特征的Activity。 如果有多个Activity符合该要求时,系统将会以下拉列表的形式列出所有的Activity,然后由用户选择具体启动哪一个,这些Activity既可以是本应用程序的,也可以是其他应用程序的。 Intent一般格式: Intent intent = new Intent(this,OtherActivity.class)
4.1.3 启动和关闭Activity finish():结束当前Activity; finishActivity(int requestCode):结束以startActivityForResult(Intent intent,int requestCode)方法启动的Activity。 注意:大部分情况下,不建议显式调用这些方法关闭Activity。因为Android系统会为我们管理Activity的生命周期,调用这些方法可能会影响用户的预期体验。因此,只有当你不想用户再回到当前Activity的时候才去关闭它。 一个包括名称、标题、启动、结束的Activity例子演示
4.1.4 Activity的生命周期 Activity的生命周期主要方法: (1) onCreate():创建Activity时被调用; (2) onStart():启动Activity时被调用; (3) onRestart():重新启动Activity时被调用; (4) onResume():恢复Activity时被调用; (5) onPause():暂停Activity时被调用; (6) onStop():停止Activity时被调用; (7) onDestory: 销毁Activity时被调用; 备注:以上方法可以通过重载生成(步骤):在Activity中右键→sources→Override,然后就可以看到右上图的界面
4.1.4 Activity的生命周期 Activity的三个主要状态: (1) Resumed:已恢复状态.此时Activity位于前台,并获得焦点,该状态也称为运行时状态。 (2) Paused:暂停状态。在该状态下,其他Activity获得焦点,该Activity仍可见,即仍存在于内存中,保存着自身状态,与窗口管理器保持联系,但如果系统内存极度匮乏时,可能会被杀死。 (3) Stopped:停止状态。在该状态下,该Activity完全被其他Activity 覆盖,即仍存在于内存中,保存着自身状态,与窗口管理器失去联系, 系统在需要内存时,可以随时杀死该Activity 。
5.1.4 Activity的生命周期 Activity的生命周期的三个循环: 整个生命周期(onCreate-onDestroy) 可见生命周期(onStart-onStop) 前台生命周期(onResume-onPause)
4.1.4 Activity的生命周期 (1)整个生命周期 从onCreate()开始到onDestroy()结束。Activity在onCreate()进行初始化,设置所有的“全局”状态,在onDestory()释放所有的资源。 例如:某个Activity有一个在后台运行的线程,用于从网络下载数据,则该Activity可以在onCreate()中创建该线程,在onDestory()中停止该线程。
4.1.4 Activity的生命周期 (2)可见生命周期 从onStart()开始到onStop()结束。在这段时间,可以看到Activity在屏幕上,尽管有可能不在前台,不能和用户交互。在这两个方法之间,需要保持显示给用户的UI数据和资源等。 例如:可以在onStart中注册一个IntentReceiver来监听数据变化导致UI的变动,当不再需要显示时候,可以在onStop()中注销它。onStart(),onStop()都可以被多次调用,因为Activity随时可以在可见和隐藏之间转换。
4.1.4 Activity的生命周期 (3)前台生命周期 从onResume()开始到onPause()结束。在这段时间里,该Activity处于所有 Activity的最前面,和用户进行交互。 Activity可以经常性地在resumed和paused状态之间切换。 例如:当设备准备休眠时、当一个 Activity处理结果被分发时、当一个新的Intent被分发时。所以在这些方法中的代码应该属于非常轻量级(与系统交互调用较少)的。
4.1.4 Activity的生命周期 案例:模拟Activity生命周期中方法的调用。重写Activity生命周期中的方法,方法调用时,在控制台打印出相应的信息,根据信息查看方法调用顺序(singleinstance)。 问题与讨论 1、若用户直接按Home键,返回到桌面,该Activity是否还存在? 2、用户按Back键返回与在其他Activity中添加一个跳转到MainActivity之间返回有什么区别?(在OtherActivity中添加返回按钮处理事件)
4.1.5 Activity间交换数据 Acitvity间传递数据的方法——采用Activity对象 数据传递的方向有两个: 当一个Activity启动另一个Activity时,常常会有一些数据需要传 过去,Intent就是它们之间的信使,主要是将需要交换的数据放 入Intent即可。 数据传递的方向有两个: 从当前Activity传递到新启动的Activity 从新启动的Activity返回结果到当前Activity。
4.1.5 Activity间交换数据 交换数据整个执行步骤:(启动其他Activity并返回结果 ) 1、为了获取被启动的Activity所返回的结果,可以采用startActivityForResult(Intent intent,int requestCode)启动新Activity,并且当前Activity需要重写 onActivityResult(int requestCode, int resultCode,Intent intent)方法。 2、被启动的Activity 执行结束前,调用自身的setResult(int resultCode,Intent intent)方法,将需要返回的结果写入到Intent中。
4.1.5 Activity间交换数据 请求码与结果码的作用 在一个Activity中,可能存在多个控件,每个控件都可能会调用startActivityForResult()方法,从而可能打开多个不同的Activity处理不同的业务。但这些Activity关闭后,都会调用先前的Activity的onActivityResult()方法。通过请求码,我们就知道该方法由哪个控件所触发,通过结果码,我们就知道返回的数据来自于哪个Activity。
4.1.5 Activity间交换数据 Intent保存数据的方法 putExtras(String name,XXX data):其中XXX代表数据类型,如int,long,String等。 putExtras(Bundle data):向intent中放入一个简单的数据携带包,该类提供了多个方法来存入数据。(查看Bundle)
用户注册案例
用户注册案例 运行界面分析
用户注册程序分析
用户注册案例 例子 1 1 2 BundleTest例子演示(男女选项) 查看RegisterTest例子,并完善程序(gender部分,if部分) 1 2
4.2 Intent详解 什么是Intent? Android应用程序中,有三种核心组件:Activity, Service,BroadcastReceiver,它们是独立的,可以互相调用,协调工作,最终组成一个真正的Android应用。这些组件的通讯,主要是由Intent协助完成的。 Intent中文翻译为‘意图’,是对一次即将运行的操作的抽象描述,包括操作的动作,涉及的数据等,Android系统会根据Intent的描述,找到相应的组件,并将Intent传递给调用的组件,完成组件的调用。
4.2.1 Intent详解 例如,我们通过前例‘注册Activity’选择所在地信息,点击‘所在地’按钮后,能够弹出‘选择城市Activtiy’进行选择,并返回结果。 为了实现这个目的,‘注册Activity’需要构造一个Intent,这个Intent 用于告诉系统,我们要做“启动”动作,此动作对应的启动对象是‘选择城市Activtiy’ ,然后调用startActivity (Intent intent),将构造的Intent 传入,系统会根据此Intent 中的描述,到AndroidManifest.xml中找到满足此Intent 要求的Activity,系统会调用找到的‘选择城市Activity’,最终传入Intent,对应的Activity则会根据此Intent 中的描述,执行相应的操作。
4.2.1 Intent详解 No. 方法 类型 描述 1 startActivity(Intent intent) 普通 startActivityForResult(Intent intent, int requestCode) 启动并接收另一个Activity程序回传数据,当requestCode大于等于0才可以触发onActivityResult() 3 getIntent() 返回启动当前Activity程序的Intent 4 onActivityResult(int requestCode, int resultCode, Intent data) 当需要接收Intent回传数据的时候覆写此方法对回传操作进行处理
4.2.2 Intent构成 component(组件):指定Intent的目标组件的类名称。通常 Android会根据Intent 中包含的其它属性的信息,比如action、data/type、category进行查找,最终找到一个与之匹配的目标组件。 但是,如果 component这个属性有指定的话,将直接使用它指定的组件,而不再执行上述查找过程。 指定了这个属性以后,Intent的其它所有属性都是可选的。Intent的Component属性需要接受一个ComponentName对象,创建一个ComponentName需要指定包名和类名。这就可唯一地确定一个组件类,这样应用程序即可根据给定的组件类去启动特定的组件。
4.2.2 Intent构成 代码如下: 等价于: 在启动的组件中,通过以下语句获取相关的信息: ComponentName comp=new ComponentName(Context con,Class class); Intent intent=new Intent(); Intent.setComponent(comp); 等价于: Intent intent=new Intent(Context con,Class class); 在启动的组件中,通过以下语句获取相关的信息: ComponentName comp=getIntent().getComponent(); comp.getPackageName();//获取组件的包名 comp.getClassName();//获取组件的类名 ComponentAttr例子
4.2.2 Intent构成 action(动作): Intent的Action代表该Intent所要完成的一个抽象“动作”,这个动作具体由哪个组件来完成,Action这个字符串本身并不管。 比如Android提供的标准Acton:Intent.ACTION_VIEW,它只表示一个抽象的查看操作,但具体查看什么,启动哪个Activity 来查看,它并不知道(这取决于Activity的<intent-filter…/>配置,只要某个Activity的<intent-filter…/>配置中包含了该ACTION_VIEW,该Activity就有可能被启动)。
4.2.2 Intent构成 Intent类中部分Action常量表: No. Action常量名称 描述 AndroidManifest.xml配置名称 描述 1 ACTION_MAIN android.intent.action.MAIN 作为一个程序的入口,不需要接收数据 2 ACTION_VIEW android.intent.action.VIEW 用于数据的显示 3 ACTION_DIAL android.intent.action.DIAL 调用电话拨号程序 4 ACTION_EDIT android.intent.action.EDIT 用于编辑给定的数据 5 ACTION_PICK android.intent.action.PICK 从特定的一组数据之中进行数据的选择操作 6 ACTION_RUN android.intent.action.RUN 运行数据 7 ACTION_SEND android.intent.action.SEND 调用发送短信程序 8 ACTION_GET_CONTENT android.intent.action.GET_CONTENT 根据指定的Type来选择打开操作内容的Intent 9 ACTION_CHOOSER android.intent.action.CHOOSER 创建文件操作选择器
4.2.2 Intent构成 category(类别): 被执行动作的附加信息。例如CATEGORY_ LAUNCHER 表示Intent的接收者应该在Launcher中作为顶级应用出现;而CATEGORY_ALTERNATIVE表示当前的Intent是一系列的可选动作中的一个,这些动作可以在同一块数据上执行。 一个Intent对象最多只能包括一个Action属性,程序可调用的setAction(String str)方法来设置Action属性值;但一个Intent对象可以包含多个Category属性,程序可调用Intent的addCategory(String str)方法来为Intent添加Category属性。当程序创建Intent时,该Intent默认启动Category属性值为Intent.CATEGORY_DEFAULT常量的组件。
4.2.2 Intent构成 Intent类中部分Category常量表: No. Category常量名称 AndroidManifest.xml配置名称 描述 1 CATEGORY_DEFAULT android.intent.category.DEFAULT 默认的Category 2 CATEGORY_BROWSABLE android.intent.category. BROWSABLE 指定该Activity能被浏览器安全调用 3 CATEGORY_TAB android.intent.category.TAB 指定该Activity作为TabActivity的Tab页 4 CATEGORY_LAUCHER android.intent.category.LAUCHER Activity显示在顶级程序列表中 5 CATEGORY_HOME android.intent.category.HOME 设置该Activity随系统启动而运行 查看Intent文档 ActionCateAttr例子讲解
4.2.2 Intent构成 Data(数据): Data属性通常用于向Action属性提供操作的数据。不同的Action通常需要携带不同的数据,如果Acition是ACTION_CALL,那么数据部分将会是tel:电话号码。Data属性接受一个URI对象,一个URI对象通常通过如下形式的字符串来表示: content://com.android.contacts/contacts/1 tel:13876523467 上面所示的两个字符串的冒号前面大致指定了数据的类型,冒号后面的是数据部分。因此一个合法的URI对象既可决定操作哪种数据类型的数据,又可指定具体的数据值。
4.2.2 Intent构成 常见的数据类型及数据URI: No. 操作类型 Data(Uri)格式 范例 1 浏览网页 http://网页地址 http://www.mldn.cn 2 拨打电话 tel:电话号码 tel:01051283346 3 发送短信 smsto:短信接收人号码 smsto: 13621384455 4 查找SD卡文件 file:///sdcard/文件或目录 file:///sdcard/mypic.jpg 5 显示地图 geo:坐标,坐标 geo:31.899533,-27.036173
4.2.2 Intent构成 type(数据类型):显式指定Intent的数据类型(MIME)。一般Intent的数据类型能够根据数据本身进行判定,但是通过设置这个属性,可以强制采用显式指定的类型而不再进行推导。通常来说当Intent不指定Data属性时Type属性才会起作用,否则Android系统将会根据Data属性来分析数据的类型。 extras(附加信息):是其它所有附加信息的集合,以键值对的形式保存所有的附加信息。使用extras可以为组件提供扩展信息(putXXX(),getXXX()方法)。比如,如果要执行“发送电子邮件”这个动作,可以将电子邮件的标题、正文等保存在extras里,传给电子邮件发送组件。
4.2.2 Intent构成 <intent-filter.../>元素是AndroidManifest.xml文件中<activity…/>元素的子元素,该子元素用于配置该Activity所能“响应”的Intent。 <intent-filter…/>元素里通常可包含如下子元素: 0-N个<action…/>子元素 0-N个<category…/>子元素 0-1个<data…/>子元素 当<activity…/>元素里的<intent-filter…/>子元素里包含多个<action…/>子元素(相当于指定了多个字符串)时,就表明该Activity能响应Action属性值为其中任意一个字符串的Intent。
4.2.3 Intent解析 Android如何解析Intent? 直接(显式)Intent:指定了component 属性的Intent(调用setComponent(ComponentName) 。通过指定具体的组件类,通知应用启动对应的组件。 间接(隐式)Intent:没有指定component 属性的Intent。这些Intent 需要包含足够的信息,这样系统才能根据这些信息,在所有的可用组件中,确定满足此Intent 的组件。隐式Intent经常用于激活其他应用程序的组件。
4.2.3 Intent解析 注意: 理论上说, 一个intent对象如果没有指定category, 它应该能通过任意的category 测试。有一个例外: android把所有传给startActivity()的隐式intent看做至少有一个category: “android.intent.category.DEFAULT”。 因此, 想要接受隐式intent的activity,必须在intent filter中加入“android.intent.category.DEFAULT”。(“android.intent.action.MAIN” 和“android.intent.category.LAUNCHER”的intent filter例外,它们不需要"android.intent.category.DEFAULT"。)
4.2.3 Intent解析 Intent解析的判断方法如下: 如果Intent指明了Action,则目标组件的IntentFilter的Action列表就必须包含这个Action,否则不能匹配。 如果Intent没有提供Type,系统将从Data中得到数据类型。目标组件的数据类型列表必须包含Intent的数据类型,否则不能匹配。 如果Intent中的数据不是content类型的URI,且Intent也没有明确指定它的Type类型,将根据Intent中数据的Scheme进行匹配,例如:“http:”,“tel:”. 如果Intent指定了一个或多个Category,这些类别必须全部出现在组件的类别列表中。
4.2.3 Intent解析 Intent解析的匹配过程如下: 1) Android系统把所有应用程序包的IntentFilter集合在一起,形成一个完整的Intent过滤器列表; 2) 在Inent与InentFilter进行匹配时,Android系统会将列表中所有过滤器的“action”和“category”与Intent进行匹配,任何不匹配的Intent过滤器将被过滤掉; 3) 把Intent数据URI的每个子部分与Intent过滤器的<data>标签的属性进行匹配,任何不匹配的Intent过滤器将会被过滤掉; 4) 如果Intent过滤器的匹配结果超过一个,则可以根据在<intent-filter>标签中定义的优先级标签来对Intent过滤器进行排序,优先级最高的Intent过滤器将被选择(优先级相同,则以列表形式供用户选择)。
Intent使用案例