【Android】活动之间的穿梭

news2024/9/24 1:20:44

引入

在活动的初学建立了一个简单的活动,但只有一个活动不是过于简单,在你使用手机的时候按下一个按钮可能会跳转到下一个界面,此时就是活动之间的穿梭:使用Intent在活动之间穿梭

Intent:是android程序中各组件之间进行交互的一种重要方式,它不仅可以指明当前组件想要执行的动作,还可以在不同组件之间传递数据。大致可分为显式Intent隐式Intent

使用显式Intent

Intent有多个构造函数的重载,其中一个为Intent(Context packageContext, Class<?> cls):第一个参数Context要求提供一个启动活动的上下文,第二个参数Class即为指定想要启动的目标活动,通过这个构造就可以直接告诉Intent的意图

在使用之前我们先创建了两个活动,第一个主活动有一个按钮Button1,第二个活动有一个按钮Button2,我们需要按下第一个按钮使其跳转到第二个活动

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/Button_1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button1"/>

</LinearLayout>

activity_second.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".SecondActivity">
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/Button_2"
        android:text="Button 2"/>

</LinearLayout>

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.ActivityTest"
        tools:targetApi="31">
        <activity
            android:name=".SecondActivity"
            android:exported="false" />
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

在主活动下写下按下Button1按钮带来的事件,代码如下:

Button button1 = (Button) findViewById(R.id.Button_1);
//按下Button1按钮使其跳转到第二个活动界面
button1.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
          Intent intent = new Intent(MainActivity.this, SecondActivity.class);
          startActivity(intent);
      }
});

即可完成上述要求,在第一个活动页面按下Button1则会跳转到第二个活动界面,此时按下back按钮就可以销毁第二个活动,返回到主活动

使用隐式Intent

隐式Intent:并不明确指出我们想要重启哪一个活动,而是指出一系列更为抽象的action和category等信息,然后交由系统去分析这个Intent,并帮我们找出合适的活动(就是可以响应我们这个隐式Intent的活动)去启动

  1. 此时我们需要修改AndroidManifest.xml中的代码,在第二个活动部分修改
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.ActivityTest"
        tools:targetApi="31">
        <!--是否能被其他应用访问:android:exported="false"-->
        <activity
            android:name=".SecondActivity"
            android:exported="false" >
            <intent-filter>
                <action android:name="com.example.activitytest.ACTION_START"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
<action android:name="com.example.activitytest.ACTION_START"/>:这个标签声明了一个特定的动作,即ACTION_START。这个动作是自定义的,由com.example.activitytest这个命名空间限定。这意味着只有当Intent包含这个特定的动作时,配置了这个<intent-filter>的组件才会被触发,就会自动触发这个活动
<category android:name="android.intent.category.DEFAULT"/>:这个标签声明了Intent所属的类别。这里的是一种默认的category,在调用 startActivity()方法的时候会自动将其添加到Intent中。
  1. 修改主活动下按钮的点击事件:
Button button1 = (Button) findViewById(R.id.Button_1);
//按下Button1按钮使其跳转到第二个活动界面:隐式Intent,即根据action与category的同时匹配确定所要进入的活动
button1.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent("com.example.activitytest.ACTION_START");
        startActivity(intent);
    }
});

我们使用的是另外一个Intent的构造函数,将action字符串直接传了进去,表明我们所要响应的活动。注意一个Intent只能指定一个action,但是可以指定多个category

指定多个category(以加入了android.intent.category.MY_DEFAULT为例):

主活动代码修改:

button1.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent("com.example.activitytest.ACTION_START");
        intent.addCategory("android.intent.category.MY_DEFAULT");
        startActivity(intent);
});

修改AndroidManifest.xml中的代码:

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

带来的效果仍为按下第一个按钮会跳转到第二个活动,但是与上一个不同在于,上一个是在按钮中直接声明要跳转到第二个活动,而这个是根据AndroidManifest.xml活动中的标签声明来确定到底是哪个活动,必需要将所有的标签声明匹配完毕,才可跳转到对应界面

更多隐式Intent的用法

使用隐式Intent不仅可以启动自己程序内的活动,还可以启动其他程序的活动,这就为Android多个应用程序之间的功能共享成为了可能

  1. 修改主活动的代码,使其跳转到指定的页面(百度):
button1.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setData(Uri.parse("http://baidu.com"));
        startActivity(intent);
    }
});
Intent intent = new Intent(Intent.ACTION_VIEW):使用Intent.ACTION_VIEW作为动作。这个动作是Android系统中预定义的,用于表示查看数据的操作。在这种情况下,它告诉Android系统我们想要查看网页。
intent.setData(Uri.parse("http://baidu.com")):这里使用Uri.parse()方法将字符串"http://baidu.com"转换成`Uri`对象。这个`Uri`对象代表了要查看的数据的地址,即百度的主页。

注意:我们可以在标签中再配置一个标签,用于更精确地指定当前活动能够响应什么类型的数据,主要配置:

  1. android:scheme:用于指定数据的协议部分,如上例中的http部分
  2. android:host:用于指定数据的主机名部分,如上例中的www.baidu.com部分
  3. android:port:用于指定数据的端口部分,一般紧随在主机名之后
  4. android:path:用于指定主机名和端口之后的部分,如一段网址中跟在域名之后的内容
  5. android:mimeType:用于指定可以处理的数据类型,允许使用通配符的方式进行指定

运行之后:
按下Button1按钮就会跳转到百度页面:
在这里插入图片描述

  1. 创建一个活动使其打开网页:

创建一个活动为ThirdActivity:

修改AndroidManifest.xml中的代码:

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

注:具体来说,AppLinkUrlError是一个错误检查,它可能会在XML布局文件中检测到一个android:autoLink属性时被触发。android:autoLink属性用于指定文本中的URL、地址、电话号码等应该自动转换为可点击的链接。使用tools:ignore="AppLinkUrlError"属性可以告诉Android Studio忽略这个错误。

主活动中代码修改:

button1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(Intent.ACTION_VIEW);
            startActivity(intent);
        }
});

按下按钮的结果:
在这里插入图片描述

  1. 其他协议:指定其他的协议(tel:表示拨打电话;geo:表示地理位置等)
button1.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent(Intent.ACTION_DIAL);
        intent.setData(Uri.parse("tel:10086"));
        startActivity(intent);
    }
});

按下按钮的结果:
在这里插入图片描述

向下一个活动传递数据

主活动的代码:

Button button1 = (Button) findViewById(R.id.Button_1);
button1.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        String data = "Hello SecondActivity";
        Intent intent = new Intent(MainActivity.this,SecondActivity.class);
        intent.putExtra("extra_data",data);
        startActivity(intent);
    }
});
  1. Intent intent = new Intent(MainActivity.this,SecondActivity.class):这行代码创建了一个Intent对象,用于启动SecondActivityMainActivity.this是当前上下文(这里是MainActivity),SecondActivity.class是要启动的Activity的类。
  2. intent.putExtra(“extra_data”,data):这行代码使用putExtra方法将字符串data作为额外的数据添加到Intent中。"extra_data"是一个键,用于在目标Activity中检索这个数据。
  3. startActivity(intent):这行代码调用startActivity方法,并传入之前创建的Intent对象。这将启动SecondActivity,并且携带了之前添加的额外数据。

第二个活动的代码:

Intent intent = getIntent();
String data = intent.getStringExtra("extra_data");
Log.d("SecondActivity",data);

第二行代码:这行代码使用getStringExtra方法从Intent中提取一个名为"extra_data"的额外数据项。getStringExtra是一个便捷方法,专门用于检索字符串类型的额外数据。如果Intent中没有这个键的数据,或者数据不是字符串类型,将返回null

运行日志打印:
在这里插入图片描述

返回数据给上一个活动

从AndroidX库的Activity Result API开始,你可以使用ActivityResultContracts,它提供了一种更现代、类型安全的方式来启动Activity并接收结果。

例如,使用ActivityResult API:

主活动代码:

public class MainActivity extends BaseActivity {
    private ActivityResultLauncher<Intent> activityResultLauncher;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        Log.d("MainActivity", "task id is " + getTaskId());
        setContentView(R.layout.activity_main);
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
            Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
            return insets;
        });

        //由第二个活动返回数据给主活动
        activityResultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
            if (result.getResultCode() == RESULT_OK) {
                Intent data = result.getData();
                if (data != null) {
                    String resulyData = data.getStringExtra("data_return");
                    Log.d("MainActivity", resulyData);
                }
            }
        });
    }
}
  1. ActivityResultLauncher 类: 这个类提供了注册回调的方法,例如 registerForActivityResult,它允许你注册一个 ActivityResultCallback 来接收启动的 Activity 的结果。
  2. 代码使用registerForActivityResult方法注册了一个ActivityResultLauncher。这个方法接受两个参数:一个ActivityResultContract的实例,在这个例子中是ActivityResultContracts.StartActivityForResult,它表示启动一个Activity并接收结果的标准契约;第二个参数是一个lambda表达式,用于定义当Activity的结果返回时如何处理。
  3. lambda表达式的主体部分,用于处理从SecondActivity返回的结果。首先检查结果码是否为RESULT_OK,这表示SecondActivity成功完成了操作。然后,尝试从返回的Intent中获取数据。如果数据不为空,从中提取字符串数据"data_return",并使用Log.d输出到日志。
  4. Button1按钮的点击事件,调用activityResultLauncher.launch(intent)启动SecondActivity。使用launch方法而不是startActivityForResult,因为我们已经通过ActivityResultLauncher处理了结果。

第二个活动中的代码:

Button button2 = (Button) findViewById(R.id.Button_2);
button2.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent();
        intent.putExtra("data_return", "Hello MainActivity");
        setResult(RESULT_OK,intent);
        finish();
    }
});

setResult方法用于设置SecondActivity的结果码和返回数据。第一个参数RESULT_OK表示操作成功完成,第二个参数是包含返回数据的Intent对象。finish方法用于关闭当前的SecondActivity,将其从用户界面中移除。

注意:

注意:当我们在第二个活动页面按下按钮返回到第一个活动界面会给第一个活动返回数据,但是当我们直接按下back按钮,则没有了返回数据,通过以下方法来解决,在SecondActivty中:

public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        // 这里实现Back键的自定义逻辑
        Intent intent = new Intent();
        intent.putExtra("data_return", "Hello MainActivity");
        setresult(RESULT_OK, intent);
        finish();
        return true; // 返回true表示事件已处理
    }
    return super.onKeyDown(keyCode, event);
}
  1. onKeyDownActivity类的一个方法,用于监听按键事件。当用户按下任何键时,这个方法会被调用。参数keyCode表示被按下的键的代码,event是对应的KeyEvent对象。
  2. KeyEvent.KEYCODE_BACK是一个常量,表示Back键的键码。这个条件判断用于检查是否按下了Back键。

运行日志打印:
在这里插入图片描述
到这里就结束了!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1929678.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【LeetCode力扣】006. Z 字形变换(Python)

最快解法 参考了运行时间最短的代码&#xff0c;其使用的思路就是按列排序后连接。 class Solution:def convert(self, s: str, numRows: int) -> str:if numRows < 2 : # numRows1时候&#xff0c;对应输出为原字符串return sn len(s)lst [ for _ in range(numRows…

andon系统在电力设备工管理中起到那些作用与价值

安灯系统&#xff0c;作为精益制造执行中的一个核心工具&#xff0c;在电力设备工厂车间管理中发挥着不可替代的作用&#xff0c;它能够实现生产透明管理&#xff0c;为工厂高效运作提供强大的支撑。本文将从安灯系统的功能、应用场景和价值三个方面&#xff0c;深入探讨其在电…

如何保证数据库和redis的数据一致性

1、简介 在客户端请求数据时&#xff0c;如果能在缓存中命中数据&#xff0c;那就查询缓存&#xff0c;不用在去查询数据库&#xff0c;从而减轻数据库的压力&#xff0c;提高服务器的性能。 2、问题如何保证两者的一致性 先更新数据库在删除缓存 难点&#xff1a;如何保证…

微信小程序,订阅消息

微信小程序&#xff0c;订阅消息&#xff0c;完整流程 1.选择需要的模版 2.前端调用订阅消息 注&#xff1a;tmplIds&#xff1a;模板ID模版id,这里也可以选多个 wx.requestSubscribeMessage({tmplIds: [7UezzOrfJg_NIYdE1p*******],success (res) { console.log(res);wx.g…

论文阅读:FAST SPECTRAL CLUSTERING WITH SELF-WEIGHTED FEATURES

1 Abstract 作为主流聚类方法之一&#xff0c;谱聚类因其在非线性数据集上的良好性能而越来越受到关注。然而&#xff0c;传统的谱聚类模型计算复杂度高。同时&#xff0c;大多数这些模型在实践中未能区分噪声和有用特征&#xff0c;导致聚类性能受限。在本文中&#xff0c;我…

集成excel工具:自定义导入回调监听器、自定义类型转换器、web中的读、捕获文件格式转换错误ExcelDataConvertException

文章目录 I 封装导入导出1.1 定义工具类1.2 自定义读回调监听器: 回调业务层处理导入数据1.3 定义文件导入上下文1.4 定义回调协议II 自定义转换器2.1 自定义枚举转换器2.2 日期转换器2.3 时间、日期、月份之间的互转2.4 LongConverterIII web中的读3.1 使用默认回调监听器3.2…

React、Vue的password输入框组件,如何关闭自动填充?

有时候我们的表单使用了一个password组件&#xff0c;这时候每次打开新建&#xff0c;都会自动获取浏览器缓存的密码&#xff0c;但是它的上一个input输入框并不是用户名&#xff0c;这时候我们希望我们的表单&#xff0c;每次点开的时候密码是空的&#xff0c;让用户自动输入&…

windows下通过nginx解压包启动nginx

退出&#xff1a; taskkill /f /t /im nginx.exe 人工智能学习网站 https://chat.xutongbao.top

【ProtoBuf】初识 ProtoBuf

一、序列化概念 1、序列化和反序列化 序列化&#xff1a;把对象转换为字节序列的过程称为对象的序列化。 反序列化&#xff1a;把字节序列恢复为对象的过程称为对象的反序列化。 什么情况下需要序列化&#xff1f; 存储数据&#xff1a;当我们想把的内存中的对象状态保存到⼀…

论文翻译:Explainability for Large Language Models: A Survey

https://arxiv.org/pdf/2309.01029 目录 可解释性在大型语言模型中&#xff1a;一项调查摘要1 引言2 LLMs的训练范式2.1 传统微调范式2.2 提示范式 3 传统微调范式的解释3.1 局部解释3.1.1 基于特征归因的解释3.1.2 基于注意力的解释3.1.3 基于示例的解释 3.2 全局解释3.2.1 基…

a newer or same version is present nvidia解决方案

安装时候出现a newer or same version is present nvidia 或者Night Visual Editor 失败&#xff0c;把显卡驱动卸载掉&#xff0c;打开service.mtc 服务控制面板&#xff0c;把nvidia开头的服务全停掉&#xff0c;重新启动cuda安装程序选择自定义安装 vse visual studio相关的…

构建未来智能边缘:4G定制化ARM边缘计算网关解决方案

在当今数字化转型的时代背景下&#xff0c;边缘计算正成为连接物理世界与数字世界的关键桥梁&#xff0c;为企业提供实时数据处理和决策能力。为了满足市场对高性能、灵活且可定制的边缘计算解决方案的需求&#xff0c;一款专为各类品牌量身定制的ARMxy边缘计算网关 产品亮点&…

【C++】题解:P1259 黑白棋子的移动_递归+模拟_算法竞赛_洛谷

文章目录 P1259 黑白棋子的移动 题解题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示解题思路AC CodeEnd P1259 黑白棋子的移动 题解 Link&#xff1a;Luogu - P1259 题目描述 有 2 n 2n 2n 个棋子排成一行&#xff0c;开始为位置白子全部在左边&#xff0c;黑…

habase集群安装

解压到/opt/softs目录 tar -zxvf hbase-2.4.11-bin.tar.gz -C /opt/softs/ 改名 mv hbase-2.4.11/ hbase2.4.11 配置环境变量 修改/etc/profile vim /etc/profile 添加 #HBASE_HOME export HBASE_HOME/opt/softs/hbase2.4.11 export PATH$PATH:$HBASE_HOME/bin 修改其中的…

Redis的单线程讲解与指令学习

目录 一.Redis的命令 二.数据类型 三.Redis的key的过期策略如何实现&#xff1f; 四.Redis为什么是单线程的 五.String有关的命令 Redis的学习专栏&#xff1a;http://t.csdnimg.cn/a8cvV 一.Redis的命令 两个基本命令 在Redis当中&#xff0c;有两个基本命令&#xff1…

【计算机网络】网络基础概念

目录 一、初识网络协议 1.1 简单理解 1.2 OSI七层模型 1.3 TCP/IP四层(或五层)模型 二、网络传输基本流程 2.1 概念 2.2 报头 三、网络中的地址管理 3.1 认识IP地址 3.2 端口号 3.3 Mac地址 四、认识TCP协议和UDP协议 五、网络字节序 六、socket编程接口 6.1 so…

2024Datawhale AI夏令营---Inclusion・The Global Multimedia Deepfake Detection--学习笔记

赛题背景&#xff1a; 其实总结起来就是一句话&#xff0c;这个项目是基于目前的深度伪装技术&#xff0c;就是通过大量人脸的原数据集进行模型训练之后&#xff0c;能够生成伪造的人脸视频。这项目就是教我们如何去实现这个DeepFake技术。 Task1:了解Deepfake和跑通baseline …

电脑鼠标连点工具哪家强?2024最新鼠标连点器工具分享

在现代计算机使用中&#xff0c;鼠标作为最主要的输入设备之一&#xff0c;在日常操作和特定应用中发挥着关键作用。然而&#xff0c;某些任务可能要求用户频繁点击鼠标&#xff0c;这不仅繁琐乏味&#xff0c;还可能导致手部疲劳。为了解决这一问题&#xff0c;自动鼠标点击工…

初始c语言(2)运算符与表达式

一 c语言提供的运算符类型 以上会后续介绍 二 现阶段我们掌握如下的基本操作符 注意&#xff01;计算机的除法只会保留整数部分&#xff08;若被除数未负则不同的软件取整的结果不唯一&#xff09; 三 自加&#xff08;&#xff09;自减&#xff08;--&#xff09;符号 若为…

【区块链 + 智慧政务】区块链 +ETC 下一代公路联网收费关键技术优化项目 | FISCO BCOS应用案例

2020 年&#xff0c;我国取消省界收费站项目完成后&#xff0c;随着收费模式与收费方式的变化&#xff0c;形成了以门架为计费单元的新收 费体系&#xff1a;按照车辆通行门架数&#xff0c;RSU 天线读取 ETC 卡、电子标签 OBU 或 CPC 卡内标识的车型信息&#xff0c;车型门架计…