第一行代码学习笔记——活动之间的交互,Intent(三)

前言

  在上一节中我们了解了Activity如何在应用中正常运行,如何使用Toast发送通知以及怎样使用AppcompatActivity提供自带的标题栏中的Menu,这次我们来了解多个Activity之间如何进行信息传递。


正文

  • 什么是Intent?
      正如字面意思,Intent可以作为意图来传递,一般可以被用作启动活动,服务以及广播。并且Intent除了可以传递意图,还能够在组件之间传递数据,当然,Intent的传递也是可以跨应用的,如果目标应用的活动是对外暴露的。
      我们来看看官网是如何介绍Intent的:

      An intent is an abstract description of an operation to be performed. It can be used with startActivity() to launch an Activity, broadcast Intent to send it to any interested BroadcastReceiver components, and startService(Intent) or bindService(Intent, ServiceConnection, int) to communicate with a background Service.
      An Intent provides a facility for performing late runtime binding between the code in different applications. Its most significant use is in the launching of activities, where it can be thought of as the glue between activities. It is basically a passive data structure holding an abstract description of an action to be performed.

  • 显示Intent与隐式Intent

      当我们想要使用Intent来启动其他的组件的时候,可以以两种方式启动,第一种就是显式Intent,第二种是隐式Intent.
      Intent有多个构造函数重载,但是我们现在只需要尝试启动另一个活动即可,所以现在我们来看其中之一的构造函数重载:Intent(Context pakageContext, Class<?> cls). 该构造函数接受两个参数,第一个就是当前所在的活动上下文,第二个参数则为目标活动的类。当准备好这些后,我们就可以通过startActivity()来启动目标活动。
      首先在上一节中的应用中创建一个新的活动,这次我们直接让Android Studio自动生成就好。
    这里写图片描述
      然后将上次缩写的Button onClick()改为:

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
                startActivity(intent);
            }
        });

  以这种方式启动活动,我们称之为显示Intent.
  然后我们来看看隐式Intent是如何使用的。
  如果想使用隐式Intent启动另一个活动,需要指定目标活动的<action>以及<category>android:name.
 我们可以看看Intent()的另外的构造方法:
     Intent(Stirng action) 
  这个构造方法只需要传入一个参数,即为<action>标签的android:name
  首先,我们需要在清单文件中为第二个Activity加入<intent-filter>并插入如下代码:

            <intent-filter>
                <action android:name="woodyman.com.activitytest.TEST"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>

  <action>中通过加入包名+你想要的名称即可,而<catagory>中的DEFAULT指的是当我们使用隐式Intent没有指定category时,就从默认标签中寻找,当然,这个我们也是可以自己单独写的和上述为<action>中的名称格式相同。
  然后我们将FirstActivity中的onClick()稍作修改:

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent("woodyman.com.activitytest.TEST");
                startActivity(intent);
            }
        });

  这里没有为intent选定category,原因就是上面所说的。如果我们是自己自定义的category,那么可以使用addCategory(String category)来为intent插入我们自定义的category,同样可以达到上述的效果。但是,如果为intent加入了一个不存在的category,那么程序就会非正常退出,并给出错误信息:
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=woodyman.com.activitytest.TEST cat=[woodyman.com.activitytest.MY_CATEGORY] }
  我们只需要加上这个category就可以正常运行了,在上面的<intent-filter>中插入代码:<category android:name="woodyman.com.activitytest.TEST"/>即可。
  当然,Intent也可以用来使用系统自带的应用,例如电话簿,拨号,相机等,个别权限需要在清单文件申请使用权限,即在<manifest>下插入:<uses-permission android:name="权限名称"/>,如果是个别敏感权限,不仅要在清单文件中申请,还要在调用相关代码前动态申请权限,才能够正常使用,具体有哪些权限可以参考后面的链接。而在代码中如果要申请使用权限,可以在Intent下找到相关的字符串常量,直接可以作为参数传入Intent(),
  其中有些权限在书中也有提到并做了相关的举例:
  需要打开一个网页,我们可以为Intent()传入Intent.ACTION_VIEW
  然后为其加入我们想要打开的网页并转变为Uri,我们使用Uri.parse(),如下所示输入代码:
    intent.setData(Uri.parse("https://www.baidu.com"))
  或者也可以使用Intent(String action, Uri uri),在第二个参数传入我们想要打开的网页并将其解析转为Uri对象即可,如下所示:
    Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.baidu.com"));
  后面的几个例子也是同理。
  当我们为intent传入不同协议的的数据的时候,只有在<intent-filter>中拥有相同协议的活动才能够响应:
  我们如果需要制作有特定功能的活动(比如上面所讲的打开网页这一目的),我们需要在清单文件中,为该活动的<intent-filter>插入相关的<data>,具体有如下几类:
  android:scheme. 用来制定协议的协议部分,如http, https, tel等。
  android:host. 用来制定数据的主机名部分。
  android:port. 用来指定数据的端口。
  android:path. 用来指定端口后具体的路径部分.
  android.mimeType. 用来指定可以处理的数据类型,可以使用通配符的方式进行指定。
组合在一起的uri格式为:<scheme>://<host>:<port>[<path>|<pathPrefix>|<pathPattern>]

  • 活动之间的数据传递
      当我们需要从活动A想活动B传输数据的时候,同样可以使用Intent来实现,只要使用putExtra(String name, XX data)以及getXXExtra(String name)就可以实现数据的存取。intent中,数据是以键值对的方式保存的:
      putExtra(String name, XX data)中,第一个参数name就是键,而第二个参数就是值,可以是多种类型。
      getXXExtra(String name)中,仅接受键就可以返回相应的值,但是返回对应的值需要对应名称的方法。
      如果当B处理完并想将相关的数据返还给A,那么我们需要在A中将startActivity()改为startActivityForResult(),两方法目的都是相同的,只是在后这需要多输入一个参数,请求码。
      startActivityForResult(Intent intent, int requestCode)中,第一个参数为intent,第二个参数为请求码,用于确定发出该信息的来源。
      然后在B中将需要返回的数据放入intent中,并作为setResult()的参数即可:
      setResult(int resultCode, Intent data),第一个参数为结果码,在书中所讲是用来返回处理结果的,一般只使用RESULT_OKRESULT_CANCELED,第二个参数为待返回数据的intent.
      之后可以在A中调用onActivityResult(int requestCode, int resultCode, Intent data)方法,来处理返回的数据,通过第一个参数和第二个参数,我们可以确定该数据是的来源以及结果是否正确,第三个参数就是我们需要的数据了。
      当然结果码如果是由自己确定的,也可以用来判定返回于哪一个组件或者活动的。

参考文章:

Android权限详细列表
Android Developer: data标签
请求码(requestCode)与结果码(resultCode)解析

上一节内容:第一行代码学习笔记——活动 Activity(二)
下一节内容:第一行代码笔记——活动的生命周期(四)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Broadcast 广播是 Android 系统中的一种重要的组件通信方式,它可以让应用程序之间消息传递,从而实现应用程序之间的数据交换和功能协同。广播可以被用来处理一些系统事件或应用程序内部的特定事件。在本篇文章中,我们将学习如何在 Android 应用程序中使用广播。 一、广播的基本概念 广播是指一种可以跨应用程序发送和接收消息的机制,它允许应用程序向全局范围内的其他应用程序通知某些事件的发生。Android 中的广播可以分为两类: 1.标准广播(Normal Broadcast):这种广播是完全异步的,所有的接收者都会在同一时刻接收到广播消息,因此它们之间没有任何优先级的区别。使用标准广播时,所有接收者都无法终止广播的传播,这也是标准广播的一个缺点。 2.有序广播(Ordered Broadcast):这种广播是同步执的,所有的接收者都是按照优先级顺序依次接收广播消息的。在广播传递过程中,每个接收者都可以截断广播的传播,使得后面的接收者无法收到广播消息。如果某个接收者截断了广播的传播,那么其后面的接收者就无法收到广播消息。这种广播的优先级由高到低依次为:1000、500、0、-500、-1000。 二、发送和接收广播 1.发送广播 在 Android 应用程序中,我们可以通过以下代码来发送广播: ```java Intent intent = new Intent("com.example.broadcasttest.MY_BROADCAST"); sendBroadcast(intent); ``` 上述代码中,我们首先创建了一个 Intent 对象,然后将其 action 设置为 "com.example.broadcasttest.MY_BROADCAST",这个 action 可以自己定义。最后,我们调用了 sendBroadcast() 方法来发送广播。 2.接收广播 要接收广播,需要在代码中注册一个 BroadcastReceiver 对象,并在其 onReceive() 方法中处理广播消息。以下是一个简单的例子: ```java public class MyBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Toast.makeText(context, "Received in MyBroadcastReceiver", Toast.LENGTH_SHORT).show(); } } ``` 在上述代码中,我们创建了一个 MyBroadcastReceiver 类,并实现了其 onReceive() 方法。当收到广播消息时,系统会自动调用该方法,并将广播消息以 Intent 对象的形式传递给该方法。在 onReceive() 方法中,我们可以根据 Intent 对象中携带的信息来进相应的处理,例如弹出一个 Toast 提示框。 3.注册广播接收器 在 Android 应用程序中,我们需要使用 IntentFilter 对象来指定要接收的广播类型。以下是一个注册广播接收器的例子: ```java MyBroadcastReceiver receiver = new MyBroadcastReceiver(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction("com.example.broadcasttest.MY_BROADCAST"); registerReceiver(receiver, intentFilter); ``` 在上述代码中,我们首先创建了一个 MyBroadcastReceiver 对象,然后创建了一个 IntentFilter 对象,并将要接收的广播类型设置为 "com.example.broadcasttest.MY_BROADCAST"。最后,我们调用 registerReceiver() 方法来注册广播接收器。 4.注销广播接收器 当我们不再需要接收某个广播时,应该及时将其注册的广播接收器进注销。以下是一个注销广播接收器的例子: ```java unregisterReceiver(receiver); ``` 在上述代码中,我们调用 unregisterReceiver() 方法来注销广播接收器。 三、有序广播的使用 有序广播可以让我们按照优先级顺序接收广播消息,并且可以截断广播的传播。以下是一个有序广播的例子: ```java Intent intent = new Intent("com.example.broadcasttest.MY_BROADCAST"); sendOrderedBroadcast(intent, null); ``` 在上述代码中,我们调用了 sendOrderedBroadcast() 方法来发送有序广播。由于没有指定接收者的权限,因此我们将其设置为 null。 接下来,我们需要在代码中注册一个 BroadcastReceiver 对象,并在其 onReceive() 方法中处理广播消息。以下是一个简单的例子: ```java public class MyBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String msg = getResultData(); Toast.makeText(context, msg + " Received in MyBroadcastReceiver", Toast.LENGTH_SHORT).show(); setResultData("Hello MainActivity"); } } ``` 在上述代码中,我们首先调用 getResultData() 方法来获取上一个接收者设置的数据,然后弹出一个 Toast 提示框,并将自己的数据设置为 "Hello MainActivity"。 接下来,我们需要指定广播接收者的优先级。在 AndroidManifest.xml 文件中,我们可以使用 priority 属性来设置广播接收者的优先级。以下是一个简单的例子: ```xml <receiver android:name=".MyBroadcastReceiver"> <intent-filter> <action android:name="com.example.broadcasttest.MY_BROADCAST"/> </intent-filter> <priority android:priority="1000" /> </receiver> ``` 在上述代码中,我们将 MyBroadcastReceiver 类注册为广播接收者,并将其优先级设置为 1000。 为了演示有序广播的效果,我们可以再注册一个 BroadcastReceiver 对象,并将其优先级设置为 500。以下是一个简单的例子: ```java public class AnotherBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String msg = getResultData(); Toast.makeText(context, msg + " Received in AnotherBroadcastReceiver", Toast.LENGTH_SHORT).show(); setResultData("Hello MainActivity"); } } ``` 在上述代码中,我们将 AnotherBroadcastReceiver 类注册为广播接收者,并将其优先级设置为 500。 最后,我们在 AndroidManifest.xml 文件中注册这两个广播接收者,代码如下: ```xml <receiver android:name=".MyBroadcastReceiver"> <intent-filter> <action android:name="com.example.broadcasttest.MY_BROADCAST"/> </intent-filter> <priority android:priority="1000" /> </receiver> <receiver android:name=".AnotherBroadcastReceiver"> <intent-filter> <action android:name="com.example.broadcasttest.MY_BROADCAST"/> </intent-filter> <priority android:priority="500" /> </receiver> ``` 在上述代码中,我们将 MyBroadcastReceiver 和 AnotherBroadcastReceiver 类都注册为广播接收者,并指定了它们的优先级。 在执上述代码后,我们可以看到,在发送广播时,首先会将广播消息发送给优先级为 1000 的 MyBroadcastReceiver 类,然后再发送给优先级为 500 的 AnotherBroadcastReceiver 类。在 MyBroadcastReceiver 类的 onReceive() 方法中,我们可以获取到 AnotherBroadcastReceiver 类设置的数据,然后弹出一个 Toast 提示框,并将自己的数据设置为 "Hello MainActivity"。最后,我们可以看到,弹出的 Toast 提示框中显示的内容为 "Hello MainActivity Received in MyBroadcastReceiver",这表明 MyBroadcastReceiver 类成功地截断了广播的传播。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值