Intent的基本知识

我们知道,Intent 是一个消息传递对象,使用它可以向其他Android组件请求操作。Intent的基本用途主要包括:启动 Activity、启动服务、传递广播。Intent分为显式Intent和隐式Intent。下面我通过启动Activity来讲解学习Intent。

Intent对象可以封装传递下面6种信息:

  1. 组件名称(ComponentName)
  2. 动作(Action)
  3. 种类(Category)
  4. 数据(Data)
  5. 附件信息(Extra)
  6. 标志(Flag)

下面来讲解这些信息

1、组件名称(CompomentName)

组件名称指定要访问的组件,但也是构建显式 Intent 的一项重要信息,如下所示:

Intent intent = new Intent(LoginActivity.this, HomeActivity.class);

startActivity(intent);

这样我们就启动了HomeActivity组件。

通过构造函数指定组件名称是我们常用的方式,此外还可以通过以下三种方法指定组件名称

Intent setClass (Context packageContext,  Class cls);

Intent setClassName (Context packageContext, String className);

Intent setClassName (String packageName, String className);

Intent setComponent (ComponentName component)

这里首先需要说明是的CompomentName对象,它定义了一个组件的基本信息,通过Android的源代码我们可以看到,其实不论哪种方法,最终Intent都会创建一个CompomentName对象封装被调用的组件信息。

其次我们来看一下Intent setClassName (String packageName, String className);这个方法。packageName指的是组件所属APP的包名。也就是AndroidManifest.xml中指定的包名,如下图所示:

最后,需要说明的是,如果传递字符串形式的className,必须指定类的全名,包括类所属的命名空间。下面给出了一个样例代码:

Intent intent = new Intent();

intent.setClassName("com.practise.salary.nvwa", "com.practise.salary.nvwa.HomeActivity");

startActivity(intent);

设置Intent的组件名称,调用相关的组件,我们称为显式调用,一般用于调用APP自身的组件,当然,我们也可以通过显式调用其他APP的组件,后面讲解显示调用时,我们在来学习。

2、动作(Action)

所谓动作就是与Activity、Service、BroadcastRecvier绑定的一个字符串,通常在AndroidManifest.xml声明组件时,设置动作参数,如下图所示:

我们可以通过设置Action属性,调用相关的组件,这称为隐式调用。

一般我们通过Intent的setAction方法设置Intent的动作,这样系统会根据动作中指定的字符串查找匹配的组件。如下所示代码:

Intent intent = new Intent();

intent.setAction("android.intent.action.MAIN");

startActivity(intent);

当我们定义自己的操作,建议将应用的软件包名称作为前缀,动作名称用大写。

3、种类(Category)

运行上面的代码,大家会发现,弹出了一个选择框,选在调用那个组件,如下图所示:

Intent的基本知识_第1张图片

之所以会出现这种情况,是因为动作“android.intent.action.MAIN”对应的组件不止一个,Android系统无法判断到底调用那个组件(详细的筛选过程将在后面过滤规则中讲解)。

Intent的Category的就是为了解决这类冲突问题的,Category的设置也是在AndroidManifest.xml文件中完成,如下图所示:

Category也是一个字符串,我们可以通过addCategory为Intent添加Category,可以添加多个Category,如下面代码所示:

Intent intent = new Intent();

intent.setAction("com.practise.salary.nvwa.action.HOME");

/*

我们可以不用手动添加android.intent.category.DEFAULT,系统会自动添加这个Category

*/

intent.addCategory("android.intent.category.DEFAULT");  

startActivity(intent);

 我们可以通过文件夹、文件类比Category和Action。

 4、数据(Data)

在Intent的隐式调用中,系统要根据请求对满足条件的组件进行筛选,这就是Intent的筛选机制。筛选条件除了Action、Category外,还有一个就是Data。此外Data还承担了简单的数据传递工作。

组件Data的申明如下图所示:

Intent的基本知识_第2张图片

下面我们学习一下Intent的Data属性。

Data包括MIME Type和URI。

MIME Type指数据的类型,例如:video/mp4,video/avi通常我们通过

Intent setType (String type)

或者

Intent setTypeAndNormalize (String type)

完成MINE Type的设置。不同之处在于setTypeAndNormalize可以规范MINE Type。

URI,统一资源标识符(Uniform Resource Identifier,或URI)是一个用于标识某一资源名称的字符串,URI可以表示成如下格式:

scheme://host:port/path

       其中

  1. scheme:协议表示,如http,https,ftp,content等;
  2. host:主机名称
  3. port:端口号
  4. path:具体的资源路径;

我们常见的URL地址就是一种特殊的URI。

我们可以通过

 

Intent setData (Uri data)

Intent setDataAndNormalize (Uri data)

来设置Intent的URI,注意此处需要传递的是一个Uri对象,该对象封装了具体的URI,我们采用如下静态方法江URI字符串转换成URI对象。

Uri parse (String uriString)

此外我们还可以调用setDataAndType一次性设置URI和MIME Type。

Intent setDataAndType (Uri data, String type)

Intent setDataAndTypeAndNormalize(Uri data, String type)

需要注意的是,当我们调用setType方法设置MIME Type,会自动清理URI的属性值,当调用setData方法来设置URI时,会自动清理MIME Type的值,如果要同时设置URI和MIMIE Type,必须使用setDataAndType方法。

关于如何通过Data进行过滤,后面我们会讲到,下面我们通过一个样例来讲解如何通过Data完成简单的数据传递。

我们通过显示调用Intent同时设置Intent的Data。代码如下:

Intent intent = new Intent(LoginActivity.this, HomeActivity.class);

intent.setDataAndType(Uri.parse("content://findUser/20180910"), "nvwa/user");

startActivity(intent);

       在被调用的HomeActivity中,我们通过getItent()获取传递来的Intent。然后我们就可以通过

Uri getData ()

String getDataString ()

获取URI,有了URI我们就可以解析出其中数据。下面给出被调用的组件的样例代码

Intent intent = getIntent();

Uri uri = intent.getData();

Log.v("URI参数传递", uri.getPath());

输出结果如下图所示:

Uri类提供了更多的方法用于处理Uri值,可参考Uri相关的帮助 https://developer.android.google.cn/reference/android/net/Uri

5、附件信息(Extra)

通过Data只能传输比较简单的数据,Intent主要通过Extra完成组件之间的数据传递。

调用方通过intent的putExtra设置数据,被调用的组件通过getXXXExtra获取数据,代码如下所示:

调用方传递参数

Intent intent = new Intent(LoginActivity.this, HomeActivity.class);

intent.putExtra("userName", "zhangw");

intent.putExtra("loginTime", Calendar.getInstance());

startActivity(intent);

被调方获取参数

Intent intent = getIntent();

Log.v("Extra数据传递", intent.getStringExtra("userName"));

我们分析Android代码可以发现,其实通过Exctra传递的是一个Bundle,我们可以把Bundle理解成一个键值对,他通过putXXX设置数据,通过getXXX读取数据。我们可以自己定义一个Bundle对象,进行数据的传递,下面给一个样例程序。

       调用方传递参数

Bundle bundle = new Bundle();

bundle.putString("userName", "account");

bundle.putSerializable("loginTime", Calendar.getInstance());

intent.putExtras(bundle);

被调方获取参数

Intent intent = getIntent();

Bundle bundle = intent.getExtras();

Log.v("登录时间", bundle.getSerializable("loginTime").toString());

输出结果如下图:

注意,调用方通过intent的getExtras获取传递的来的bundle。

       6、标记(Flag)

      Intent通过

Intent setFlags (int flags)

设置标记。   关于标记的用法,后面我们用到后再给大家将,这并不表示这个概念不重要。

(张伟:2018年9月27日)

(转载时请注明来源)

你可能感兴趣的:(Android程序设计)