android应用开发----Intent和Activity的跳转

Intent的简介:

是Android中用于组件(Activity,Service,BroadcastReceiver,ContentProvider)之间传递信息的对象,相当于组件间通信的”信使“,它不仅能启动目标组件,还能携带数据(如文本,图片,对象等)进行传递

       核心作用:

                启动组件:打开新的activity(点击按钮跳转到详情页),启动后台service(如下载文件,播放音乐),触发BroadcastReceiver(监听网络变化,电量低提醒)

                传递数据:在Activity之间传递参数(如列表想点击后传递ID到详情页),向service传递操作指令(如暂停/播放音乐),在广播中携带状态信息(如网络连接状态变更)

                声明组件能力:通过Intent Filter定义组件能相应的Intent类型(如某个Activity可以打开网页连接)

          分类:       

类型显式 Intent隐式 Intent
核心特点明确指定目标组件的类名不指定类名,通过动作(Action)、类别(Category)、数据(Data)匹配目标组件
使用场景应用内组件跳转(如 Activity 之间)跨应用调用(如打开系统相机、浏览器)或应用内解耦(如插件化)
示例代码Intent(this, TargetActivity::class.java)Intent(Intent.ACTION_VIEW, Uri.parse("https://www.example.com"))
匹配方式直接根据类名查找,成功率 100%系统根据 Intent Filter 匹配,可能匹配多个组件或失败

 使用显示Intent

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

参数一:Context要求提供一个启动Activity的上下文

参数二:第二个参数Class用于指定想要启动的目标Activity

通过Intent的构造函数可以构建出Intent的意图。

Activity类中提供了一个startActivity()方法,专门用于启动Activity,它接受一个Intent参数。

 显示Intent实现Activity跳转

        

在这我们首先构建了一个Intent对象,

第一个参数传入this也就是FirstActivity作为上下文,

第二 个参数传入SecondActivity::class.java作为目标Activity

注意,Kotlin中 SecondActivity::class.java的写法就相当于Java中SecondActivity.class的写法

来再通过startActivity()方法执行这个Intent就可以

在FirstActivity中设置按钮,然后为按钮设置点击事件,添加后跳转至新的Activity

class MainActivity : AppCompatActivity() {
    private val TAG = "MainActivity"
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main_layout)
        findViewById<Button>(R.id.btn1).setOnClickListener{
            val intent = Intent(this,MainActivity1::class.java)
            startActivity(intent)
        }
        Log.d(TAG,"onCreate()方法被执行")
    }
}

按一下Back键就可以销毁当前Activity,从而回到上一个Activity,因为这种方式意图特别明显,所以称为显示Intent

隐式Intent

相比于显式Intent,隐式Intent则含蓄了许多,它并不明确指出想要启动哪一个Activity,而是 指定了一系列更为抽象的action和category等信息,然后交由系统去分析这个Intent,并帮 我们找出合适的Activity去启动。

首先在AndroidManiFest.xml中添加指定当前Activity能够相应的action和category

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

在<action>标签中我们指明了当前Activity可以响应”com.example.activitytest.ACTION_

START“这个action,而<category>标签则包含了一些附加信息,更精确的指明了当前Activity能够响应的Intent中还可能带有的category,只有<action>和<category>中的内容同时匹配Intent中指定的action和category时,这个Activity才能响应该Intent

修改实现跳转按钮的点击事件,即可完成跳转:

button1.setOnClickListener {
     val intent = Intent("com.example.activitytest.ACTION_START")
     //为android.intent.category.DEFAULT是一种默认的category,
    //在调用startActivity()方法的时候会自动将这个category添加到Intent中
     startActivity(intent)
}

若在若在AndroidManifest.xml中.SecondActivity中新增category

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

那么也可通过新增的实现跳转

button1.setOnClickListener {
     val intent = Intent("com.example.activitytest.ACTION_START")
     intent.addCategory("com.example.activitytest.MY_CATEGORY")
     startActivity(intent)
}

更多隐式Intent的用法

1.实现Intent传递数据

        Intent中提供了一系列putExtra()方法的重载,可以把我们想要传递的数据暂存在Intent中,在启动另一个Activity后,只需要把这些数据从Intent中取出来就可以了。

例如下方FirstActivity中有一个字符串,现在想把这个字符串传递到SecondActivity中。

在FirstActivity中设置按钮,增加监听事件,点击后发送数据

button1.setOnClickListener {
     val data = "Hello SecondActivity"
     val intent = Intent(this, SecondActivity::class.java)
     //参数一:”存储数据的键“
     //参数二:”真正传递的数据“
     intent.putExtra("extra_data", data)
     startActivity(intent)
}

在SecondActivity中取出数据

class SecondActivity : AppCompatActivity() {
     override fun onCreate(savedInstanceState: Bundle?) {
           super.onCreate(savedInstanceState)
           setContentView(R.layout.second_layout)
           //此处实际上调用父类的getIntent()方法,该方法会获取用于启动SecondActivity
           //然后调用getStringExtra()方法并传入相应的键值,就可以得到传递的数据了
           //这里由于我们传递的是字符串,所以使用getStringExtra()方法来获取传
                                                                递的数据。
          //如果传递的是整型数据,则使用getIntExtra()方法;
          //如果传递的是布尔型数据,
          //则使用getBooleanExtra()方法,以此类推。
            val extraData = intent.getStringExtra("extra_data")
            Log.d("SecondActivity","extra data is $extraData")
     }
}

2.销毁Activity(此处后面会做详细介绍)

        Android中的Activity是可以层叠的,我们每启动一个新的Activity,就会覆盖在原Activity之上,然后点击Back键会销毁最上面的Activity,下面的一个Activity就会重新显示出来

        Android使用任务(task)来管理Activity的,一个任务就是一组存放在栈里的Activity的集合,这个栈也被称为返回栈(back stack).栈是一种先进后出的数据结构,在默认情况下,每当我们启动了一个新的Actvity,它就会在返回栈中入栈,并处于栈顶的位置。而每当我们按下Back键或调用finish()方法去销毁一个Activity时,处于栈顶的Activity就会出栈,前一个入栈的Activity就会重新处于栈顶的位置。系统总是会显示处于栈顶的Activity给用户

3.向上一个Activity返回数据

方式一:startActivityForResult()-------------(已弃用,但是老旧代码依旧使用)

        那么我们利用Intent让FirstActivity发送数据给SecondActivity,那么再能不能让SecondActivity发送数据给FirstActivity呢,答案是可以的,Activity类中还有一个用于启动Activity的StartActivityForResult()方法,但它期望在Activity销毁的时候能够返回一个结果给上一个Activity。

startActivityForResult()方法接收两个参数:

参数一:Intent

参数二:请求码(用于在之后的回调中判断数据的来源,只要唯一值)

首先还是通过在FirstActivity中设置按钮,点击后跳转至SecondActivity

button1.setOnClickListener {
    
     val intent = Intent(this, SecondActivity::class.java)
     //改变启动Activity的方法
     startActivityForResult(intent, 1)
}

然后在SecondActivity中设置发送的数据

class SecondActivity : AppCompatActivity() {
   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       
       setContentView(R.layout.second_layout)
       
       button2.setOnClickListener {
       //将数据存放在Intent中
       val intent = Intent()
       intent.putExtra("data_return", "Hello FirstActivity")
       //专门用于向上一个Activity返回数据的方法
           //参数一:用于向上一个Activity返回处理结果
                 一般只使用RESULT_OK或RESULT_CANCELED这两个值
           //参数二:则把带有数据的Intent传递回去
       setResult(RESULT_OK, intent)
       //销毁当前Activity
       finish()
       }
   }
}

如果通过按钮实现返回至FirstActivity,那么实现下方逻辑,在FristActivity中重写方法,

由于在一个Activity中有可能调用 startActivityForResult()方法去启动很多不同的Activity,每一个Activity返回的数据都 会回调到onActivityResult()这个方法中,因此我们首先要做的就是通过检查 requestCode的值来判断数据来源。确定数据是从SecondActivity返回的之后,我们再通过 resultCode的值来判断处理结果是否成功。最后从data中取值并打印出来,这样就完成了向 上一个Activity返回数据的工作。

//参数一:requestCode及我们在启动Activity时传入的请求码
//参数二:resultCode 即我们在返回数据时传入的处理结果
//参数三: data  即携带着返回数据的Intent
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
     super.onActivityResult(requestCode, resultCode, data)
     when(requestCode){
           1 ->if(resultCode == RESULT_OK){
                 val returnedData = data?.getStringExtra("data_return")
                 Log.d("FirstActivity","returned data is $returnedData")
           }
     }
}

如果通过手机的back键(返回键)实现返回至FirstActivity,那么实现下方逻辑,在FristActivity中重写方法,

override fun onBackPressed() {
     val intent = Intent()
     intent.putExtra("data_return", "Hello FirstActivity")
     setResult(RESULT_OK, intent)
     finish()
}
方式二:使用 Activity Result API -------------------新代码推荐

这是现在新代码推荐的方式;

1. FirstActivity(启动方)

class FirstActivity : AppCompatActivity() {

    // 1. 注册Activity Result Launcher
    private val startSecondActivity = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
        if (result.resultCode == RESULT_OK) {
            // 3. 处理返回的数据
            val data = result.data
            val message = data?.getStringExtra("message") ?: ""
            Toast.makeText(this, "接收到: $message", Toast.LENGTH_SHORT).show()
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_first)

        // 2. 启动SecondActivity
        findViewById<Button>(R.id.btn_start_second).setOnClickListener {
            val intent = Intent(this, SecondActivity::class.java)
            startSecondActivity.launch(intent)
        }
    }
}

2. SecondActivity(返回数据方)

class SecondActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_second)

        // 设置返回数据并关闭
        findViewById<Button>(R.id.btn_return_data).setOnClickListener {
            val returnIntent = Intent()
            returnIntent.putExtra("message", "来自SecondActivity的数据")
            setResult(RESULT_OK, returnIntent)
            finish()
        }

        // 取消操作
        findViewById<Button>(R.id.btn_cancel).setOnClickListener {
            setResult(RESULT_CANCELED)
            finish()
        }
    }
}

4.利用Intent跳转打开浏览器

使用隐式Intent,不仅可以启动自己程序内的Activity,还可以启动其他程序的Activity,这就 使多个应用程序之间的功能共享成为了可能。比如你的应用程序中需要展示一个网页,这时你 没有必要自己去实现一个浏览器(事实上也不太可能),只需要调用系统的浏览器来打开这个 网页就行了。

button1.setOnClickListener {
    //指定Intent的action为Intent.ACTION_VIEW
    //这是一个Android系统内置的动作,其常量值为android.intent.action.VIEW
     val intent = Intent(Intent.ACTION_VIEW)
     //通过Uri.parse()方法将一个网址字符串解析成一个Uri对象
     //再调用Intent的setData()方法将这个Uri对象传递进去
     intent.data = Uri.parse("https://www.baidu.com")
     startActivity(intent)
}

还可以在<intent-filter>标签中再配置一个<data>标签,用于更精确地指 定当前Activity能够响应的数据。<data>标签中主要可以配置以下内容。

android:scheme用于指定数据的协议部分,如上例中的https部分。

android:host用于指定数据的主机名部分,如上例中的www.baidu.com部分。

android:port用于指定数据的端口部分,一般紧随在主机名之后。

android:path用于指定主机名和端口之后的部分,如一段网址中跟在域名之后的内

容。

android:mimeType用于指定可以处理的数据类型,允许使用通配符的方式进行指定。

只有当<data>标签中指定的内容和Intent中携带的Data完全一致时,当前Activity才能够响应 该Intent。

<activity android:name=".ThirdActivity">
     <intent-filter tools:ignore="AppLinkUrlError">
           //配置当前能够响应的action为Intent。ACTION_VIEW常量值
           <action android:name="android.intent.action.VIEW" />
           //指定默认的category值
           <category android:name="android.intent.category.DEFAULT" />
           //指定了数据的协议必须时https协议
           <data android:scheme="https" />
     </intent-filter>
</activity

另外,由于Android Studio认为所有能够响应ACTION_VIEW的Activity都应该加上BROWSABLE的category,否 则就会给出一段警告提醒。加上BROWSABLE的category是为了实现deep link功能,和我们 目前学习的东西无关,所以这里直接在<intent-filter>标签上使用tools:ignore属性将 警告忽略即可

5.利用Intent跳转拨打电话

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

首先指定了Intent的action是Intent.ACTION_DIAL,这又是一个Android系统的内置动 作。然后在data部分指定了协议是tel,号码是10086

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java失业转安卓

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值