Android显式意图和隐式意图

Posted 我想月薪过万

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android显式意图和隐式意图相关的知识,希望对你有一定的参考价值。

intent基本理解

  • 我们都知道android四大组件:Activity 、Service、broadcast receiver 及 内容提供者。
  • 其中,Activity 、Service、broadcast receiver 三大组件之间的通信 intent 起着至关重要的作用,即 媒介。
  • intent 可以激活 Android 应用的三个核心组件:活动(Activity)、服务(Service)和广播接收器(BroadcastReceiver)

显式意图 和 隐式意图

显示意图:在创建 intent 的时候明确指定了组件名,例如:调用 Intent.setComponent() 或Intent.setClass() 或 使用构造器来指定组件( new Intent(MainActivity.this, OtherActivity.class)

隐式意图:在创建 intent 的时候没有明确指定组件名,而是 系统根据 设置的 动作(action)、类别(category)、数据(data: URI和数据类型)找到最合适的组件来处理这个意图。

隐式意图代码示例

第一步:创建 SecondActivity 

package com.wust.intenttest;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

import androidx.annotation.Nullable;

/**
 * ClassName: SecondActivity <br/>
 * Description: <br/>
 * date: 2021/10/24 22:49<br/>
 *
 * @author yiqi<br />
 * @QQ 1820762465
 * @微信 yiqiideallife
 * @技术交流QQ群 928023749
 */
public class SecondActivity extends Activity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TextView textView = new TextView(this);
        textView.setText("我是secondView");
        setContentView(textView);
    }
}

第二步:在 清单文件 中声明

<activity android:name=".SecondActivity">
            <intent-filter>
                <!-- 自定义的动作 一般前缀为包名-->
                <action android:name="com.wust.intenttest.SECOND"/>
                <!-- 附加信息 这个必须得加上-->
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
</activity>

如果你在清单文件中 没有加 <category android:name="android.intent.category.DEFAULT"/> ,就会报如下错误,这是因为 你在调用 startActivity()的时候系统自动给你的意图添加了 android:name="android.intent.category.DEFAULT" 这个类别,所以你在清单文件中不声明,系统当然自动匹配不上,除非你不用隐式意图。

第三步:跳转代码

public void tz(View v) {
        //这里我们使用隐式意图 所以不指明是哪个组件
        Intent intent = new Intent();
        intent.setAction("com.wust.intenttest.SECOND");
        // 这个类别系统会自动添加
        intent.addCategory(Intent.CATEGORY_DEFAULT);
        startActivity(intent);
}

第四步:传递 Uri 数据

我们可以通过Intent的Data、Type、Extra传入一些数据,这些数据可以用于进一步筛选匹配Activity,打开指定的页面、文件,或者给准备启动的Activity传入需要的参数。

这个时候我们再新建一个 ThirdActivity.java 

package com.wust.intenttest;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

import androidx.annotation.Nullable;

/**
 * ClassName: ThirdActivity <br/>
 * Description: <br/>
 * date: 2021/10/25 9:57<br/>
 *
 * @author yiqi<br />
 * @QQ 1820762465
 * @微信 yiqiideallife
 * @技术交流QQ群 928023749
 */
public class ThirdActivity extends Activity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TextView textView = new TextView(this);
        textView.setText("我是ThirdView");
        setContentView(textView);
    }
}

同时在 清单文件 中进行声明

<activity android:name=".SecondActivity">
            <intent-filter>
                <!-- 自定义的动作 一般前缀为包名-->
                <action android:name="com.wust.intenttest.SECOND" />
                <!-- 附加信息 这个必须得加上-->
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
</activity>

<activity android:name=".ThirdActivity">
            <intent-filter>
                <!-- 自定义的动作 一般前缀为包名-->
                <action android:name="com.wust.intenttest.SECOND" />
                <!-- 附加信息 这个必须得加上-->
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
</activity>

我们可以发现 我们注册 SecondActivity 和 ThirdActivity 的时候 给的筛选条件 action 、category 是一样的。所以但我们仍然执行第三步的跳转代码时,系统就会让我们进行选择了,运行效果如下图:

这个时候,我们的 data 筛选条件就起作用了,我们不妨在  ThirdActivity 声明的时候加上如下筛选条件:

<activity android:name=".ThirdActivity">
            <intent-filter>
                <!-- 自定义的动作 一般前缀为包名-->
                <action android:name="com.wust.intenttest.SECOND" />
                <!-- 附加信息 这个必须得加上-->
                <category android:name="android.intent.category.DEFAULT" />
                <!-- 自定义的scheme,还有别的属性,自行尝试 -->
                <data android:scheme="http"/>
            </intent-filter>
</activity>

这个时候,我们再 执行第三步的跳转代码 毫无疑问,当然是跳转到 SecondActivity。效果如下:

但是,这个效果并不是我要说的重点,我们重点是看如何通过 data 来传递 uri 数据。 所以,我们对 第三步 的跳转代码进行如下改造:

public void tz(View v) {
        // 这里我们使用隐式意图 所以不指明是哪个组件
        Intent intent = new Intent();
        intent.setAction("com.wust.intenttest.SECOND");
        // 这个类别系统会自动添加
        intent.addCategory(Intent.CATEGORY_DEFAULT);
        // 设置数据
        intent.setData(Uri.parse("http://121.0.0.1"));
        startActivity(intent);
}

相应的  ThirdActivity 也得作出相应的接收

package com.wust.intenttest;

import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.widget.TextView;

import androidx.annotation.Nullable;

/**
 * ClassName: ThirdActivity <br/>
 * Description: <br/>
 * date: 2021/10/25 9:57<br/>
 *
 * @author yiqi<br />
 * @QQ 1820762465
 * @微信 yiqiideallife
 * @技术交流QQ群 928023749
 */
public class ThirdActivity extends Activity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TextView textView = new TextView(this);
        textView.setText("我是ThirdView");
        setContentView(textView);

        Uri data = getIntent().getData();
        System.out.println( "data.getHost() => " + data.getHost());
        System.out.println( "data.getScheme() => " + data.getScheme());
    }
}

运行效果如下:

所有对于 data 这个筛选项 我们搞清楚以下三个地方:

清单文件中

<data android:scheme="http" android:host="127.0.0.1" android:port="80" android:path="/mypath" android:mimeType="wust/yiqi"/>

跳转代码

intent.setDataAndType(Uri.parse("http://127.0.0.1:80/mypath"), "wust/yiqi");

获取数据代码

data.getScheme()://data.getHost():data.getPort()data.getPath()

显式意图

如果大家把上面的 隐式意图 搞清楚,显式意图简直就是小草一碟。

根据 显式意图 的定义,我们在创建 intent 的时候,明确那个要跳转的组件即可。

第一步:代码示例

public void tz(View v) {
        // 这里我们使用显式意图 所以指明是哪个组件
        Intent intent = new Intent(this,SecondActivity.class);
        startActivity(intent);
}

第二步:传递 action 、category、data,请参考隐式意图

跳转代码

public void tz(View v) {
        // 这里我们使用显式意图 所以指明是哪个组件
        Intent intent = new Intent(this,SecondActivity.class);
        intent.setAction("com.wust.intenttest.SECOND");
        // 这个类别系统会自动添加
        intent.addCategory(Intent.CATEGORY_DEFAULT);
        // 设置数据
        intent.setDataAndType(Uri.parse("http://127.0.0.1:80/mypath"), "wust/yiqi");
        startActivity(intent);
}

数据获取代码 在目标组件中编写,这里的目标组件为 SecondActivity

Uri data = getIntent().getData();
System.out.println("data.getHost() => " + data.getPath());
System.out.println("data.getScheme() => " + data.getScheme());

效果展示

 

以上是关于Android显式意图和隐式意图的主要内容,如果未能解决你的问题,请参考以下文章

隐式意图Intent

Android 之 Intent(意图)

显式intent和隐式intent

Android Activity之间的跳转

【Android】显式/隐式Intent意图跳转Activity总结

Android学习笔记06