Android 7.20-1 Intent

2 用Intent实现Activity之间的跳转

一个应用一般情况下不会就只有一个Activity,那么如何实现不同Activity之间的跳转呢

2.1 显示Intent

在当前包路径下New一个空Activity,勾选如图
在这里插入图片描述
点击Finish,将自动生成的second_layout中的代码替换掉

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:id="@+id/button_2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button_2"/>
</LinearLayout>

准备工作做完了,我们现在来看看Intent
Intent是Android程序中各组件之间进行交互的一种重要方式,它不仅可以指明当前组件想要执行的动作,还可以在不同组件之间传递数据
Intent的作用一般有三种:

  1. 启动Activity
  2. 启动Service
  3. 发送广播

我们现在学启动Activity,Service和广播后面涉及到再学
Intent大致可以分为两种

  1. 显式Intent
  2. 隐式Intent

Intent有多个构造函数的重载,其中一个Intent(Context packageContext, Class<?> cls)的两个参数:

  1. Context要求提供一个启动Activity的上下文
  2. Class用于指定想要启动的目标Activity

通过这个构造函数就可以构建出Intent的“意图”,此外Activity类中提供了一个startActivity()方法,用于启动Activity,并接收一个Intent参数,即上面构建的Intent可以传进来,这样,就可以启动目标Activity了

将FirstActivity中按钮点击事件代码进行修改

val intent = Intent(this, SecondActivity::class.java)
startActivity(intent)

在这里插入图片描述
其中,this表示FirstActivity,SecondActivity::class.java 相当于Java中的SecondActivity.class写法

运行结果为点击button_1会跳转到SscondActivity对应的布局

这种方式之所以被称为显示Intent,是因为Intent的“意图”非常明显,val intent = Intent(this, SecondActivity::class.java),即在FirstActivity的基础上打开SecondActivity

2.2 隐式Intent

隐式Intent不会明确指出启动哪一个Activity,而是需要根据action和category等信息来匹配、分析,找出合适的Activity来启动。
简单来说,显示的Intent就是点名的时候报一个人的身份证号码;隐式的Intent就是说母亲姓李,父亲姓张,自己姓赵的三班的男生,这样的符合条件的男生虽然没有被明确点名,但是也知道叫到了自己。在隐式的Intent中,这样的锁定条件的角色就由action和category来担任了。
打开AndroidManifest.xml,修改为如下形式(即添加几行代码)

<activity android:name=".SecondActivity">
    <intent-filter>
        <action android:name="com.example.activitytest.ACTION_START"/>
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>
</activity>

在隐式Intent中声明的时候,必须action和category都匹配上的Activity,才会被认为是目标Activity,因为android.intent.category.DEFAULT是一种默认的category,在调用startActivity()的时候会自动将这个category添加到Intent中,所以只需要在Intent中添加action就好。
将点击事件中的Intent做以下修改:

	val intent = Intent("com.example.activitytest.ACTION_START")

然后运行,发现也能实现跳转功能

接下来,试试在AndroidManifest.xml中再加一条category

	<category android:name="com.example.activitytest.MY_CATEGORY"/>

在点击事件中,调用Intent的addCategory()方法

	intent.addCategory("com.example.activitytest.MY_CATEGORY")

再运行,发现能够匹配到SecondActivity

2.3 更多隐式Intent的用法

使用隐式Intent不仅可以启动自己程序的Activity,还可以启动其他程序的Activity。比如在自己程序中需要打开一个网页,只要调用系统的浏览器来打开这个网页就行了。
点击事件中的代码修改:

	val intent = Intent(Intent.ACTION_VIEW)
	intent.data = Uri.parse("http://www.baidu.com")
	startActivity(intent)

指定Intent的action是Intent.ACTION_VIEW,这是一个Android系统内置的动作。Uri.parse()方法将网址字符串解析成一个Uri对象,通过setData()方法接收。直接.data而不是.setData()是Kotlin中的语法糖,前面说过。
运行,如图,点击button_1后调用系统浏览器
在这里插入图片描述
此外,我们可以在<intent-filter>中加入<data>标签,更精确地指定当前Activity能够响应的数据,属性如下:

android:scheme	协议部分
android:host	主机名部分
android:port	端口部分
android:path	主机名和端口后面部分,跟在域名后的内容
android:mimeType	可以处理的数据类型

New一个ThirdActivity,并将third_layout.xml内容替换,在AndroidManifest.xml中修改代码

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:id="@+id/button_3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button_3"/>
</LinearLayout>

在AndroidManifest.xml中修改信息

<activity android:name=".ThirdActivity">
     <intent-filter tools:ignore="AppLinkUrlError">
           <action android:name="android.intent.action.VIEW"/>
           <category android:name="android.intent.category.DEFAULT"/>
           <data android:scheme="https"/>
     </intent-filter>
</activity>

由于AS认为所有能够响应ACTION_VIEW的Activity都应该加上BROWSABLE的category,否则就会出现警告,因此要加上Android_lint的tools:ignore。
但是我这里出现了飘红,找了很久想办法解决了飘红,解决方法在我的另一篇博客,但是功能还是不能实现,我这里先放一放了。
正常情况下运行结果是点击按钮后出现选择界面,让我们选择用浏览器还是ThirdActivity打开。

除了https协议外,我们还可以指定其他协议,比如geo表示显示地理位置、tel表示拨打电话。
将点击事件代码修改:

	val intent = Intent(Intent.ACTION_DIAL)
	intent.data = Uri.parse("tel:10086")
	startActivity(intent)

Intent.ACTION_DIAL又是一个Android系统的内置动作,tel指定协议,10086指定号码。
运行结果如图
在这里插入图片描述

2.4 Activity间的数据传递

2.4.1 向下传递

在向下一个Activity传递数据时,通过Intent.putExtra()方法保存数据,在下一个Activity中,通过getIntent()方法获取用于启动该Activity的Intent,调用Intent.getStringExtra()方法获取数据(不一定是String,可能是其他类型),另外,由于Kotlin提供的get/set的语法糖,在获取Intent时,也不用getIntent()方法,直接用intent就可以。
FirstActivity中的代码(在button_1的点击事件中)

    val data = "Hello SecondActivity"
    val intent = Intent(this, SecondActivity::class.java)
    intent.putExtra("extra_data", data)
    startActivity(intent)

SecondActivity中的代码

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.second_layout)
        val data = intent.getStringExtra("extra_data")
        Log.d("SecondActivity", "data is $data")
    }

运行结果,点击button_1后,跳转到SecondActivity,并出现日志
在这里插入图片描述

2.4.2 向上返回

在向下传递中,我们用intent来传递数据,但是我们从下一级返回上一级Activity时,并没有一个用来传递数据的Intent。不过,在Activity类中,还有一个用于启动Activity的startActivityForResult()方法,这个方法就需要在Activity销毁的时候能够返回一个结果给上一个Activity。
startActivityForResult()方法接收两个参数,第一个参数还是Intent实例,第二个参数是请求码,用于在之后的回调中判断数据的来源。

FirstActivity:

	val intent = Intent(this, SecondActivity::class.java)
    startActivityForResult(intent, 1)

请求码只要是一个唯一值就可以了,接下来在SecondActivity中加入按钮的点击事件,在其中书写添加返回数据的逻辑

    button_2.setOnClickListener {
        val intent = Intent()
        intent.putExtra("data_return", "Hello FirstActivity")
        setResult(RESULT_OK, intent)
        finish()
    }

可以看到,我们构建了一个没有“意图”的intent,仅仅用来传递数据。
之后调用了setResult()方法,这个方法专门用来向上返回数据,它接收两个参数

  1. 用于向上一个Activity返回处理结果,一般使用RESULT_OK或者RESULT_CANCELED两个值
  2. 把带有数据的intent传递回去

最后用finish()销毁当前Activity

此外,由于我们是使用startActivityForResult()方法来启动SecondActivity的,在其销毁之后会回调上一个Activity的onActivityResult()方法,因此需要子啊FirstActivity中重写这个方法来得到返回的数据。

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    when(requestCode){
        1 -> if (resultCode == RESULT_OK){
            val returnData = data?.getStringExtra("data_return")
            Log.d("FirstActivity", "returned data is $returnData")
        }
    }
}

onActivityResult()接收三个参数

  1. 在启动Activity时传入的请求码,我们传入的1
  2. 返回数据时传入的处理结果
  3. 携带者数据的intent

运行结果,点击button_1跳转带SecondActivity,点击button_2返回到FirstActivity并打印出日志
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值