转载请注明出处:http://blog.csdn.net/huiblog/article/details/53221809
五壮士之 Activity
开场白
为什么说是五壮士呢?
Android知识体系中最重要的就是四大组件,也就是Activity、Service、ContentProvider以及BrocastRecever。还有一个重要的组件Application。所以,四大组价+Application=五壮士。
这重要的五个家伙就跟人体的心、肝、脾、肺、肾一样,个个组件之间分工明确,构成了我们强大的Android体系。这里我们简单的了解一下就可以了,后续文章我们会一一聊聊的。
这是Activity系列文章第一节。
什么是Activity
概论
Activity就像人的脸面一样,这个玩意承载着一个APP的单独的一个门面。通过这个组件,我们可以让APP当前的页面中显示任何我们想要显示的东西。例如:我们看到的文字(可能是Textview这个控件)、一个按钮(可能是Button 这个控件)、
一张图片(可能是ImageView 这个控件)。为什么说可能呢?因为Android的控件是很灵活的,所看到的的不一定是真的,你看到的是按钮(Button),可能他是使用图片+文字组合在一起的。(当然,后续文章中我们会知道,Button的实质就是图片+文字组合在一起的)
UI构成简介
其实Activity并不是在对象里面添加了一个部局文件那样简单。
我们所用的布局文件其实是通过PhoneWindow放到了DecorView的mContentParent里面,最终形成了我们看到的。- 简单图示
这里就放个图在这,简单看看就行。Activity的后续文章中我会进行详解的。
Activity的跳转
我们新建一个Activity后,需要在AndroidManifest.xml这个重要的文件中进行注册我们的Activity,为什么要在这个文件中注册呢?因为这个文件相当于一个APP的简历,通过这个简历我们可以知道这个APP想要什么权限、有哪些需要展示的页面、能接受什么广播、有哪些服务、能向外界提供哪些数据,等等。
使用Android Studio 创建一个默认的APP,我们看看这个AndroidManifest.xml里都写了什么。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.asia.testactivity">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
捡当前我们讲的跳转来看,<activity android:name=".MainActivity">
这个表示MainActivity是一个Activity。而<intent-filter>
是意图过滤器在他的子节点的两行代码<action android:name="android.intent.action.MAIN" />
表示当前所在的父节点的Activity是主Activity,也就是说打开APP时,系统会默认打开这个Activity也就是这段XML中的MainActivity。具体intent-filter是干嘛的后面会讲的。
<category android:name="android.intent.category.LAUNCHER" />
Activity的跳转呢有两种跳转方法,分别是显示跳转和隐式跳转。
- 显示跳转
显示跳转就是说很明显我们知道要跳转到哪一个Activity的意思。
Demo:
Intent intent = new Intent();
intent.setClass(context, TargetActivity.class);
startActivity(intent);
执行上面的一段代码后,我们就能跳转到到指定的TargetActivity了。
另一种写法:
Intent intent = new Intent(context, TargetActivity.class);
startActivity(intent);
两种意思都一样,指定了目的Activity,使用Intent跳转。
- 隐式跳转
隐式跳转就像一种模糊跳转,就跟上网买衣服差不多,过滤条件写着冬季、蓝色、175cm的大衣,电商就列了一列衣服供你选择。隐士跳转呢,我们指定要跳转的Activity需要什么样的条件,系统会将系统中所有的应用的AndroidManifest.xml遍历一遍找到你提出条件的Activity,然后跳转到这个Activity中。如果有多个符合条件的Activity,就弹窗问你需要跳转到哪一个,如果没有找到符合条件的Activity,系统就会骂你,傻啊你,没有你这么苛刻条件的Activity,然后就抛异常了。O(∩_∩)O哈哈~
Demo主要代码
MainActivity
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e("hui", "MainActivity onCreate");
}
public void onClick(View view){
Intent intent = new Intent();
intent.setAction("my.custom.action");
intent.addCategory("android.intent.category.DEFAULT");
intent.setData(Uri.parse("mydata:lalalala"));
startActivity(intent);
}
}
AndroidManifest.xml中SecondActivity的注册代码
<activity android:name=".SecondActivity">
<intent-filter>
<action android:name="my.custom.action" />
<data android:scheme="mydata"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
效果:
上面的例子看一下,下面就详细讲解一下这个intent-filter强大的过滤功能,最后在看这个例子就明白了。
intent-filter (意图过滤器)
有三个重要的参数,action、category、data。
- action 可以翻译为功能,这个东西呢谷歌提供的是给系统用的,我们开发APP时由我们开发人员自定义的,代表着我们自己定义的这个Activity拥有什么样的功能。
- category 类别,上面写的”android.intent.category.DEFAULT”就是一般情况下用的默认类别。
category是使用系统给我们提供的,有很多种,例如:
不同的category代表着Activity的不同类别,比如第一个“”android.intent.category.BROWSABLE”代表着这是浏览器类别的。
其他的常用action及category参考这个。 data 这个东西的官方意思是“表示操作数据的URI和MIME类型”,也就是说包含了当前action所必须的数据规范。举例来说:我们调用系统的打电话的功能(setAction(Intent.ACTION_CALL))就必须要传递过去一个电话号码(setData(Uri.parse(“tel:110”))),上面两个设置后就可以给110打电话了(当然需要权限)。如果没有电话号码调用打电话的功能没意义的。 data有两个属性:
属性一:scheme
上例子中,<data android:scheme="mydata"/>
,那么如果你想打开我这个Activity就必须给我一个以mydata为前缀开头的数据,例如上面的intent.setData(Uri.parse(“mydata:lalalala”));我们获取到这个数据就可以做我们自己的操作。对于Intent#setData方法,
public Intent setData(Uri data)
需要一个 uri,我们通过public static Uri parse(String uriString)
就可以将“mydata:lalalala”传递给目的Activity了。
如果有多个scheme,例如有两个scheme约束:<data android:scheme="mydata"/>
和<data android:scheme="otherdata"/>
我们的setData方法只需要匹配其中任意一个即可,使用intent.setData(Uri.parse("mydata:xxxxx"))
或者intent.setData(Uri.parse("otherdata:xxxx"))
:其中任意一个都可以与这个intent-filter匹配属性二:mimeType
这个东西代表了传递的数据类型,比如mp4类型(audio/mpeg),3gp类型(audio/3gpp),等等。注意:格式必须是XXX/XXX类似的。使用public Intent setType(String type)
就可以了。注意!
在同时有setData和setType时,这个东西互斥的,不能同时生效。必须只能使用public Intent setDataAndType(Uri data, String mimeType)
。不知道谷歌当初怎么想的^(* ̄(oo) ̄)^。
现在看上面隐士跳转的demo代码是不是明白了许多,↖(^ω^)↗。
在SecondActivity的注册代码中,intent-filter的子节点action和category代表着这个Activity是 “android.intent.category.DEFAULT”类型的Activity,拥有”my.custom.action”功能的Activity,同时需要mydata前缀的数据。
而在MainActivity 的隐式跳转中,系统根据指定的action和category以及data的scheme遍历全部应用AndroidManifest.xml文件,发现与SecondActivity的约束条件一致,完全匹配,而且只有这一个,就打开了SecondActivity。
完全匹配的指的是,我如果要求身高175、体重50kg以上这条件,那么相亲对象就必须符合这两个条件。在代码中,意思是你必须符合我Intent-filter中的所有约束条件,才是匹配我的资格。还拿上面SecondActivity例子说明,SecondActivity的intent-filter中有action、category和data三个约束,那么你给我的intent中必须也有三个对应的约束,才能匹配。如果我的intent中只有action和category这两个约束值,那么两者是不匹配的,完全一致才匹配。
Activity跳转流程
借用Google的图示,加深理解。
无论隐式跳转还是显示跳转,流程都如上图所示,Activity A创建一个包含要跳转到目的Activity信息的Intent,然后通过startActivity将intent数据发给系统,[2]系统拿到intent后进行解析intent中数据,查询手机中所有的APP中的AndroidManifest.xml文件中的intent-filter,找与之匹配的intent-filter,【3】当找到了与之匹配的intent-filter后就打开这个Activity。找不到,就抛异常(^o^)/~
最后,看下如果有多个符合约束条件的Activity会怎么样呢?
新建第三个Activity,注册的intent-filter如下:
<activity android:name=".ThridActivity">
<intent-filter>
<action android:name="my.custom.action" />
<data android:scheme="mydata"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
全部代码:http://download.csdn.net/detail/huiblog/9686973