1.Activity的理解
- Activity 直译为活动,它是Android定义的四大应用组件之一,也是最重要用的最多的
- Activity用来提供一个能让用户操作并与之交互的界面
- 一个应用有多个界面,也就是包含多个Activity(还存在单Activity+多Fragment 的)
- 打电话、发短信、拍照、发邮件等功能都是通过Activity来做的
2.Intent的理解
- Intent 直译为意图,也就是你想要做什么或想去哪
- Intent是Activity、Service和BroadcastRecevier这个三个应用组件之间通信的信使
- 例如: 我要在Activity中启动另一个Actvity, 就必须使用Intent对象
- 意图对象还可以携带数据
- 注意: Intent不是Android中的四大应用组件之一
- Intent的分类:显式意图 : 明确指定的目标组件的意图 创建对象 : Intent(Context context, Class clazz) 何时使用 : 当操作当前自己应用的组件时使用。
隐式意图 : 没有明确指定目标组件的意图 创建对象 : Intent(String action) 何时使用 : 当操作其它应用的组件时使用。
注:在Intent内部维护了一个HashMap<String,Objec>
2.1 IntentFilter的理解
隐式调用需要Intent能够匹配目标组件的IntentFilter中所设置的过滤信息,匹配不到则无法启动 目标Activity,IntentFilter中过滤信息有action、category、data.
- 在配置Activity时, 可以为Activity指定一个IntentFilter的配置
- 如果你的Activity希望其它应用能访问到, 需要配置<intent-filter>
- 如果你想启动其它应用的界面你必须用隐式intent, 且目标界面Activty配置了<intent-filter>
- 它的作用类似于web中的为Servlet配置的<url-pattern>
2.2 Intent的七大属性(ComponentName、Action、Category、Data、Type、Extra、Flag)
Intent七大属性是指Intent的ComponentName、Action、Category、Data、Type、Extra、Flag,七个属性,总体上可以分为3类:
第一类:启动,有ComponentName(显式),Action(隐式),Category(隐式)。
第二类:传值,有Data(隐式),Type(隐式),Extra(隐式、显式)。
第三类:启动模式,有Flag。
- ComponentName: 用于指出启动的组件(实现页面的跳转)
intent = new Intent();
intent.setComponent(new ComponentName(this, SecondActivity.class));
startActivity(intent);
- Action:Action属性的值为一个字符串,它代表了系统中已经定义了一系列常用的动作。通过setAction()方法或在清单文件AndroidManifest.xml中设置。默认为:DEFAULT。
Action、Category属性与intent-filter配置:通常,Action、Category属性结合使用,定义这两个属性都是在配置文件的<intent-filter>节点中。Intent通过定义Action属性(其实就是一段自定义的字符串),这样就可以把Intent与具体的某个Activity分离,实现了解耦。否则,每次跳转,都要写成类似new Intent(MainActivity.this,NextActivity.class)这样的形式,也就是说必须将要跳转的目标Activity的名字写出来,这样的编码其实是“硬编码”,并没有实现松耦合。调用Intent对象的setAction()方法实现页面跳转虽然略微复杂(需要在AndroidManifest.xml文件中配置)1、示例代码: Intent intent = new Intent(); intent.setAction("com.train.task01.editactivity"); startActivity(intent); //在配置文件中注册Activity的时候需要声明: <activity android:name="com.train.taskstack01.EditActivity"> <intent-filter> <action android:name="com.train.task01.editactivity" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> //当某个页面是默认启动页面时,需要定义Action、Category的属性必须为以下字符串:【设置任务入口】 <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> 常用的属性 ACTION_MAIN:(android.intent.action.MAIN)Android程序入口,每个Android应用必须且只能包含一个此类型的Action声明。 ACTION_VIEW: (android.intent.action.VIEW) 显示指定数据。 ACTION_EDIT: (android.intent.action.EDIT) 编辑指定数据。 ACTION_DIAL: (android.intent.action.DIAL) 显示拨号面板。 ACTION_CALL: (android.intent.action.CALL) 直接呼叫Data中所带的号码。 ACTION_ANSWER: (android.intent.action.ANSWER) 接听来电。 ACTION_SEND: (android.intent.action.SEND) 向其他人发送数据(例如:彩信/email)。 ACTION_SENDTO: (android.intent.action.SENDTO) 向其他人发送短信。 ACTION_SEARCH: (android.intent.action.SEARCH) 执行搜索。 ACTION_GET_CONTENT: (android.intent.action.GET_CONTENT) 让用户选择数据,并返回所选数据 ACTION_BOOT_COMPLETED:Android系统在启动完毕后发出带有此Action的广播(Broadcast)。 ACTION_TIME_CHANGED:Android系统的时间发生改变后发出带有此Action的广播(Broadcast)。 ACTION_PACKAGE_ADDED:Android系统安装了新的Application之后发出带有此Action的广播(Broadcast)。 ACTION_PACKAGE_CHANGED:Android系统中已存在的Application发生改变之后(如应用更新操作)发出带有此Action的广播(Broadcast)。 ACTION_PACKAGE_REMOVED:卸载了Android系统已存在的Application之后发出带有此Action的广播(Broadcast)。
Category:Category属性用于指定当前动作(Action)被执行的环境。通过addCategory()方法或在清单文件AndroidManifest.xml中设置。默认为:CATEGORY_DEFAULT。Intent intent = new Intent(); intent.setAction(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_HOME); startActivity(intent); 常用属性 CATEGORY_DEFAULT: (android.intent.category.DEFAULT) Android系统中默认的执行方式,按照普通Activity的执行方式执行。 CATEGORY_HOME: (android.intent.category.HOME) 设置该组件为Home Activity。 CATEGORY_PREFERENCE: (android.intent.category.PREFERENCE) 设置该组件为Preference。 CATEGORY_LAUNCHER: (android.intent.category.LAUNCHER) 设置该组件为在当前应用程序启动器中优先级最高的Activity,通常与入口ACTION_MAIN配合使用。 CATEGORY_BROWSABLE: (android.intent.category.BROWSABLE) 设置该组件可以使用浏览器启动。 CATEGORY_BROWSABLE:设置该组件可以使用浏览器启动。 CATEGORY_GADGET:设置该组件可以内嵌到另外的Activity中。
- Data:Data通常是URI格式定义的操作数据。例如:tel:// 。通过setData()方法设置。
在intent-filter中指定data属性的实际目的是:要求接收的Intent中的data必须符合intent-filter中指定的data属性,这样达到反向限定Intent的作用// 打开网页 intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse("http://www.baidu.com")); startActivity(intent); // 打电话 intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse("tel:183****8515")); startActivity(intent); 常用属性 tel://:号码数据格式,后跟电话号码。 mailto://:邮件数据格式,后跟邮件收件人地址。 smsto://:短息数据格式,后跟短信接收号码。 content://:内容数据格式,后跟需要读取的内容。 file://:文件数据格式,后跟文件路径。 market://search?q=pname:pkgname:市场数据格式,在Google Market里搜索包名为pkgname的应用。 geo://latitude, longitude:经纬数据格式,在地图上显示经纬度所指定的位置。
-
Extras:Extras属性主要用于传递目标组件所需要的额外的数据。通过putExtras()方法设置。Extra可以传递基本类型,String类型以及实现了Serializable或者Parcelable接口的类。
通过intent.putExtra(键, 值)的形式在多个Activity之间进行数据交换常用属性 EXTRA_BCC:存放邮件密送人地址的字符串数组。 EXTRA_CC:存放邮件抄送人地址的字符串数组。 EXTRA_EMAIL:存放邮件地址的字符串数组。 EXTRA_SUBJECT:存放邮件主题字符串。 EXTRA_TEXT:存放邮件内容。 EXTRA_KEY_EVENT:以KeyEvent对象方式存放触发Intent的按键。 EXTRA_PHONE_NUMBER:存放调用ACTION_CALL时的电话号码。
-
Type:Type是对Data的类型作进一步的说明。Type在manifest中的设置同样也在<data>标签中,是data的mimeType属性。
mimeType包括许多文件类型,包括图片、视频、音频等等,每种类型下也可以包含多种文件格式,以下举例部分:
text/plain 纯文本 image/gif image/gif image/jpeg jpeg图像 video/mpeg MPEG动画 audio/mp3 mp3音乐 也可以不指定具体文件格式,只指定文件类型:
image/* 指定类型为image的所有文件 audio/* 指定类型为audio的所有文件 video/* 指定类型为video的所有文件
播放视频: Intent intent = new Intent(); Uri uri = Uri.parse("file:///sdcard/media.mp4"); intent.setAction(Intent.ACTION_VIEW); intent.setDataAndType(uri, "video/*"); startActivity(intent);
- Flags
FLAG_ACTIVITY_NEW_TASK 该标记的作用时为Activity 指定“singleTask”启动模式,其效果和在xml中指定该启动模式相同。 FLAG_ACTIVITY_SINGLE_TOP 该标记的作用时为Activity指定“singleTop”启动模式,其效果和在xml中指定该启动模式相同。 FLAG_ACTIVITY_CLEARP_TOP 具有此标记位的Activity,当它启动时,在同一个任务栈中所有位于它上面的Acivity都要出栈。这个标记位一般会和singleTask启动模式一起出现,在这种情况下,被启动Activity的实例已经存在,那么系统就会调用它的onNewIntent。如果被启动的Activity采用standard模式启动,那么它连同它以上的Activity都要出栈,系统会创建新的Activity实例并放入栈顶。 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 具有这个标记位的Activity不会出现在历史Activity的列表中,当某些情况下我们不希望用户通过历史列表回到我们的Activity的时候这个标记比较有用。它等同于在XML中指定Activity的属性android:excludeFromRecents="true"。
3.Activity的生命周期
- 运行状态:可见也可操作
- 暂停状态:可见但不可操作
- 停止状态:不可见,但对象存在
- 死亡状态:对象不存在
onCreate:在首次创建 Activity 时调用。系统向此方法传递一个 Bundle 对象,其中包含 Activity 的上一状态,不过前提是捕获了该状态,而后会调用onStart方法。(可以在此方法中执行所有正常的静态设置 ,比如:创建视图、将数据绑定到列表等等。)
onStart:在 Activity 即将对用户可见之前调用。而后如果Activity转入了前台就会调用onResume方法。 如果此时直接屏幕熄灭或者用户按下home键则会直接调用onStop方法,当然这种情况比较极端。
onResume:在 Activity 即将开始与用户进行交互之前调用。 此时,Activity 处于 Activity 堆栈的顶层,并具有用户输入焦点。当跳转另一个Activity,或者退出当前Activity后会调用onPause方法。
onPause:在系统即将开始继续另一个 Activity 时调用。 此方法通常用于确认对持久性数据的未保存更改、停止动画以及其他可能消耗 CPU 的内容,诸如此类。 它应该非常迅速地执行所需操作,因为它返回后,下一个 Activity 才能继续执行,所以不能执行耗时操作。而后正常情况下会调用onStop方法。但是有一种极端情况,就是如果这个时候快速让 当前Activity 返回前台,则会调用onResume方法。
onStop:在 Activity 对用户不再可见时调用。如果 Activity 被销毁,或另一个 Activity(一个现有 Activity 或新 Activity)继续执行并将其覆盖,就会调用此方法。而后如果 Activity 恢复与用户的交互,则会调用 onRestart 方法,如果 Activity 被销毁,则会调用onDestroy方法。
onRestart:在Activity被停止后再次启动时调用(即屏幕熄灭后再次回到app,按下home键后再次回到app),而后会调用onStart方法。
onDestroy:在 Activity 被销毁前调用,这是 Activity 收到的最后调用。 当 Activity 结束(对 Activity 调用了 finish 方法),或系统为节省空间而暂时销毁该 Activity 实例时,可能会调用它。 你可以通过 isFinishing 方法区分这两种情形
Activity于Fragment 周明周期
onAttach():当Activity和Fragment交互的时候,我们可以在Activity中通过 Fragment.setArguments()的方法为Fragment提供数据,然后再Fragment的onAttach()方法中 getArguments()获得一个Bundle对象。
onCreateView():创建该Fragment对应的视图,在这里你必须将创建的视图返回诶调用者。它跟onCreate()的区别:onCreate()是指创建该Fragment,你可以在其中初始化除了View之外的东西。
onActivityCreated()
当Activity的onCreate()方法调用时,该方法被调用
onDetach()
当Fragment和Activity解除关联时调用该方法。
onActivityCreated()
当Activity中的onCreate方法执行完后调用。
问题一:从A-Activity跳转到B-Activity生命周期是?
A_onCreate-->A_onStart-->A_onResume-->A_onPause-->B_onCreate-->B_onStart-->B_onResume-->A_onStop
问题二:从A-Activity跳转到B-Activity,然后再按Home的生命周期是?
A_onCreate-->A_onStart-->A_onResume-->A_onPause-->B_onCreate-->B_onStart-->B_onResume-->A_onStop-->B_onPause-->B_onStop
问题三:从A-Activity跳转到B-Activity,再返回到A-Activity
A_onCreate-->A_onStart-->A_onResume-->A_onPause-->B_onCreate-->B_onStart-->B_onResume-->A_onStop-->B_onPause-->A_onRestart--->A_onstart--->A_onResume-->B_onStop--->B_onDestroy
lauchMode 启动模式
1. standard 默认标准的启动模式,每次startActivity都是创建一个新的activity的实例。
应用场景: 适用于绝大大数情况
2. singleTop 单一顶部,如果要开启的activity在任务栈的顶部已经存在,就不会创建新的实例,
而是调用 onNewIntent() 方法。
应用场景: 浏览器的书签。 避免栈顶的activity被重复的创建,解决用户体验问题。
例如,某个新闻客户端的新闻内容页面,如果收到10个新闻推送,每次都打开一个新闻内容页面是很烦人的。
3. singleTask 单一任务栈 , activity只会在任务栈里面存在一个实例。如果要激活的activity,在任务栈里面已经存在,就不会创建新的activity,而是复用这个已经存在的activity,调用 onNewIntent() 方法,并且清空这个activity任务栈上面所有的activity
应用场景:浏览器的书签, 整个任务栈只有一个实例,节约内存和cpu的目的
注意: activity还是运行在当前应用程序的任务栈里面的。不会创建新的任务栈。
4. singleInstance 单态 单例模式
单一实例,整个手机操作系统里面只有一个实例存在。不同的应用去打开这个activity 共享公用的同一个activity。
他会运行在自己单独,独立的任务栈里面,并且任务栈里面只有他一个实例存在。
应用场景:呼叫来电界面 InCallScreen、手机联系人界面 闹钟
了解更多
Android之service两种启动方式的异同
Android之Service与IntentService区别
Android之内容提供者(ContentProvider)
Android之广播(Broadcast)
ANR 超时的定义
3个ActivityA和C为默认启动模式(standard)B为singleTask 生命周期
Intent 能传递多大 Size 的数据?(附阿里答案)