当前位置:   article > 正文

Android Intent(意图)介绍_安卓被称为意图

安卓被称为意图

对于Android Intent大家肯定不陌生,Intent顾名思义就是“意图”的意思。其实这个“意图”有点不好理解。其实简单点就是我想要“干什么”。你比如说,我想要“去火车站”、我想要“启动一个Activity”、我想要“启动一个server”、我想要XXX都是意图。Intent有显式Intent和隐式Intent两种情况。


那么问题来了:

一.那到底什么样的Intent是显式的Intent,什么样的Intent是隐式的Intent呢?

为了回答这个问题,请看下面对于隐式Intent和显式Intent的具体介绍


1 隐式Intent

说起隐式Intent就不得不先说在清单文件(AndroidManifest.xml)中的intent-filter。你随便创建一个Android 项目都会在清单文件中看见intent-filter,顾名思义就是Intent的过滤器。而且一个Activity组件的声明中,可以有多个intent-filter。当然也可以没有intent-filter。


举个例子如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3. package="com.mytest">
  4. <application
  5. android:allowBackup="true"
  6. android:icon="@mipmap/ic_launcher"
  7. android:label="@string/app_name"
  8. android:roundIcon="@mipmap/ic_launcher_round"
  9. android:supportsRtl="true"
  10. android:theme="@style/AppTheme">
  11. <!--1个intent-filter-->
  12. <activity android:name=".MainActivity">
  13. <intent-filter>
  14. <action android:name="android.intent.action.MAIN" />
  15. <category android:name="android.intent.category.LAUNCHER" />
  16. </intent-filter>
  17. </activity>
  18. <!--没有intent-filter-->
  19. <activity android:name=".Main2Activity" />
  20. <!--多个intent-filter-->
  21. <activity android:name=".Main3Activity">
  22. <intent-filter>
  23. <action android:name="com.mytest.MyIntentAction" />
  24. <category android:name="android.intent.category.DEFAULT" />
  25. <data android:mimeType="aa/bb"/>
  26. </intent-filter>
  27. <intent-filter>
  28. <action android:name="com.mytest.MyIntentAction1" />
  29. <category android:name="android.intent.category.DEFAULT" />
  30. <data android:scheme="myIntent1" android:host="8080"/>
  31. </intent-filter>
  32. <intent-filter>
  33. <action android:name="com.mytest.MyIntentAction2" />
  34. <category android:name="android.intent.category.DEFAULT" />
  35. <data android:scheme="myIntent2"/>
  36. </intent-filter>
  37. </activity>
  38. </application>
  39. </manifest>

intent-filter实行“白名单”管理,即只列出组件乐意接受的Intent,但intent-filter只会过滤隐式Intent,显式的Intent会直接传送到目标组件。 Android组件可以有一个或多个intent-filter,每个intent-filter之间相互独立,只需要其中一个intent-filter中的所有过滤条件条件(Action、Data、Category)全部被满足则验证通过。就说明该Intent是可以启动该Activity的。除了用于过滤广播的intent-filter可以在代码中创建外,其他的intent-filter必须在AndroidManifest.xml文件中进行声明。

intent-filter中具有和Intent对应的用于过滤Action,Data和Category的字段,一个隐式Intent要想被一个组件处理,必须匹配这三个(Action,Data和Category字段。下面具体介绍一下这三个字段

1.1 Action
检查 Action 尽管一个Intent只可以设置一个Action,但一个Intentfilter可以持有一个或多个Action用于过滤,到达的Intent只需要匹配其中一个Action即可。 深入思考:如果一个Intentfilter没有设置Action的值,那么,任何一个Intent都不会被通过;反之,如果一个Intent对象没有设置Action值,那么它能通过所有的Intent-filter的 Action检查。

1.2 Data
检查 Data 同Action一样,Intent-filter中的Data部分也可以是一个或者多个,而且可以没有。每个Data包含的内容为URL和数据类型,进行Data检查时主要也是对这两点进行比较,比较规则: 如果一个Intent对象没有设置Data,只有Intent-filter中也没有设置Data时才可通过检查。 如果一个Intent对象包含URI,但不包含数据类型:仅当Intent-filter也不指定数据类型,同时它们的URI匹配,才能通过检测。 如果一个Intent对象包含数据类型,但不包含URI:仅当Intentfilter也没指定URL,而只包含数据类型且与Intent相同,才通过检测。 如果一个Intent对象既包含URI,也包含数据类型(或数据类型能够从URI推断出),只有当其数据类型匹配Intent-filter中的数据类型,并且通过了URL检查时,该Intent对象才能通过检查。
其中URL由四部分组成:它有四个属性scheme、host、port、path对应于URI的每个部分。
例如:content://com.wjr.example1:121/files
       scheme部分:content
       host部分:com.wjr.example1
       port部分:121
       path部分:files

host和port部分一起构成URI的凭据(authority),如果host没有指定,那port也会被忽略。
这四个属性是可选的,但他们之间并不是完全独立的。要让authority有意义,scheme必须要指定。要让path有意思,scheme和authority必须指定。Intent-filter中的path可以使用通配符来匹配path字段,Intent和Intent-filter都可以用通配符来指定MIME类型。

1.3Category
检查 CategoryIntent-filter中可以设置多个Category,Intent中也可以含有多个Category,只有Intent中的所有Category都能匹配到Intentfilter中的Category,Intent才能通过检查。也就是说,如果Intent中的Category集合是Intent-filter中Category的集合的子集时,Intent才能通过检查。如果Intent中没有设置Category,则它能通过所有Intent-filter的Category检查。 如果一个Intent能够通过不止一个组件的Intent-filter,用户可能会被问哪个组件被激活。如果没有目标找到,会产生一个异常。

Intent-filter
应用程序的组件为了告诉Android自己能响应、处理哪些隐式Intent请求,可以声明一个甚至多个IntentFilter。每个 IntentFilter描述该组件所能响应Intent请求的能力——组件希望接收什么类型的请求行为,什么类型的请求数据。比如之前请求网页浏览器这 个例子中,网页浏览器程序的IntentFilter就应该声明它所希望接收的Intent Action是WEB_SEARCH_ACTION,以及与之相关的请求数据是网页地址URI格式。
如何为组件声明自己的IntentFilter? 常见的方法是在AndroidManifest.xml文件中用属性描述组件的IntentFilter。
前面我们提到,隐式Intent和IntentFilter进行比较时的三要素是Intent的Action、Data以及Category。实际上,一个隐式Intent请求要能够传递给目标组件,必要通过这三个方面的检查。如果任何一方面不匹配,Android都不会将该隐式Intent传递给目标组件。


讲完了AndroidManifest.xml中的Intent-filter.就要看一下如何在代码中一个隐式的Intent,去启动一个组件。下面我们来看一个代码例子,我创建了一个Android 项目,除了默认的MainActivity我又增加了两个Activity:Main2Activity、Main3Activity。


其中Main2Activity由MainActivity启动,暂时不看启动Main2Activity的代码,现在我们先看Main2Activity中使用隐式的Intent启动Main3Activity的代码。根据AndroidManifest.xml中Main3Activity的声明来看,有三个intent-filter可以启动Main3Activity,所以我随机选一个intent-filter进行Intent的设置就可以了。我选用第三个intent-filter来启Main3Activity。

  1. <intent-filter>
  2. <action android:name="com.mytest.MyIntentAction2" />
  3. <category android:name="android.intent.category.DEFAULT" />
  4. <data android:scheme="myIntent2"/>
  5. </intent-filter>

AndroidManifest.xml中的action中的内容和Data中的内容都是我随便写的,因为在android默认的那些action和data的数据中也是一个字符串,所以我们可以设置其为任意字符串。根据这个intent-filter我在Main2Activity.java中的代码实现如下:

  1. package com.mytest;
  2. import android.content.Intent;
  3. import android.net.Uri;
  4. import android.support.v7.app.AppCompatActivity;
  5. import android.os.Bundle;
  6. public class Main2Activity extends AppCompatActivity {
  7. @Override
  8. protected void onCreate(Bundle savedInstanceState) {
  9. super.onCreate(savedInstanceState);
  10. setContentView(R.layout.activity_main2);
  11. //创建隐式Intent
  12. Intent intent = new Intent();
  13. //为隐式Intent添加过滤Action,Data和Category的字段,
  14. // 不是说必须这三个字段同时有,这个设置那些是根据清单文件中Main3Activity的某一个intent-filter确定的
  15. intent.setAction("com.mytest.MyIntentAction2");
  16. intent.addCategory("android.intent.category.DEFAULT");
  17. intent.setData(Uri.parse("myIntent2:" + 110));//后边的110是随便加的,暂时没有什么具体的意思,这就是他的一个用法
  18. //启动Main3Activity
  19. startActivity(intent);
  20. }
  21. }

这就是使用隐式的Intent启动组件。


2 显式Intent

其实显式Intent就很简单了,我们直接来看代码。我在MainActivity.java中使用显式Intent启动Main2Activity,代码如下

  1. package com.mytest;
  2. import android.content.Intent;
  3. import android.support.v7.app.AppCompatActivity;
  4. import android.os.Bundle;
  5. public class MainActivity extends AppCompatActivity {
  6. @Override
  7. protected void onCreate(Bundle savedInstanceState) {
  8. super.onCreate(savedInstanceState);
  9. setContentView(R.layout.activity_main);
  10. //创建显示Intent
  11. Intent intent = new Intent(getApplicationContext(),com.mytest.Main2Activity.class);
  12. //启动Activity
  13. startActivity(intent);
  14. }
  15. }

这就是显式的Intent去启动组件。


总的一句话,如果创建Intent的时候,明确指出了要启动的class的名字,就是显示Intent。如果没有明确的指出要启动的class的名,而是通过设置intent的过滤字段启动class,就是隐式Intent.


二.什么时候用显示Intent,什么时候用隐式Itent呢?

一句话:当你启动自己写的同一个APP中的Activity时使用显示Intent,当你要启动其他人写APP中的Activity时使用隐式Intent。


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/236009
推荐阅读
相关标签
  

闽ICP备14008679号