【Android】穿梭在活动中的Intent(显式和隐式的用法,向上/向下传递数据)

一、穿梭在活动中的Intent

Intent是Android程序中各组件之间进行交互的一种重要方式,它不仅可以指明当前组件想要执行的动作,还可以在不同组件之间传递数据。Intent一般可被用于启动活动、启动服务以及发送广播等场景。

1、显式Intent

Intent有多个构造函数的重载,Intent(ContextpackageContext,Class<?>cls)是其中一个。这个构造函数接收两个参数,第一个参数Context要求提供一个启动活动的上下文,第二个参数Class则是指定想要启动的目标活动,通过这个构造函数就可以构建出Intent的“意图”。

image-20230717164010032

//得到一个intent对象
Intent intent = new Intent(getApplicationContext(), MainActivity2.class);
//运行intent对象的实例
startActivity(intent);

然后我们应该怎么使用这个Intent呢?Activity类中提供了一个startActivity()方法,这个方法是专门用于启动活动的,它接收一个Intent参数,这里我们将构建好的intent传入startActivity()方法就可以启动目标活动了。

2、隐式Intent

2.1 启动内部activity

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

通过在标签下配置intent-filter:的内容,可以指定当前活动能够响应的actioncategory,打开AndroidManifest.xml,添加如下代码:

image-20230717180107934

使用intent的另一个构造函数,直接将action的字符串传进去。

Intent intent = new Intent("android.intent.action.Button2");
//运行intent对象的实例
startActivity(intent);

2.2 启动外部activiyty

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

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setData(Uri.parse("http://www.baidu.com"));
        startActivity(intent);
        /**
          * 另一种调用方法
          * Intent intent = new Intent(Intent.ACTION_VIEW,Uri.parse("tel:10086"));
          * startActivity(intent);
          */
    }
});

image-20230717193902509

这里我们首先指定了Intent的action是Intent.ACTION VIEW,这是一个Android系统内置的动作,其常量值为android.intent.action.VIEW。然后通过Uri.parse()方法,将一个地址字符串解析成一个Uri对象,再调用Intent的setData()方法将这个Uri对象传递进去。

Intent.ACTION_VIEW是一个常量,它是Android中的一个标准动作(Action),用于指定一个Intent的目标是查看某种数据。具体而言,它表示要查看(显示)指定的数据,比如网址、地图位置、图片、文档等。

与此对应,我们还可以在标签中再配置一个标签,用于更精确地指定当前活动能够响应什么类型的数据。标签中主要可以配置以下内容。

  • android:scheme 用于指定数据的协议部分,如上例中的http部分。
  • android:host 用于指定数据的主机名部分,如上例中的www.baidu.com部分。
  • android:port 用于指定数据的端口部分,一般紧随在主机名之后。
  • android:path 用于指定主机名和端口之后的部分,如一段网址中跟在域名之后的内容。
  • android:mimeType 用于指定可以处理的数据类型,允许使用通配符的方式进行指定。
<activity
          android:name=".ThirdActivity"
          android:exported="true" >
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="https" />
    </intent-filter>
</activity>

android.intent.category.DEFAULT,表示这个Activity是一个默认的处理器,可以处理普通的View操作。

android.intent.category.BROWSABLE,表示这个Activity支持浏览(Browsing)操作。

除了https协议外,我们还可以指定很多其他协议,比如geo表示显示地理位置、tel表示拨打电话。下面的代码展示了如何在我们的程序中调用系统拨号界面。

geo参数为经纬度,tel参数为电话号码

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("tel:10086"));
        startActivity(intent);
    }
});

image-20230717212847582

3、向下一个活动传递数据

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

在上一个活动中设置信息如下:

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent intent = new Intent(getApplicationContext(), ThirdActivity.class);
        intent.putExtra("extra_data","Hello 世界");
        startActivity(intent);
    }
});

注意这里putExtra()方法接收两个参数,第一个参数是键(用于后一个活动取出数据),用于后面从Intent中取值,第二个参数才是真正要传递的数据。

在下一个活动中使用Intent获取数据

public class ThirdActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_third);
        
        Intent intent = getIntent();	//得到intent对象
        String data = intent.getStringExtra("extra_data");
        Log.d("TAG1", data);
    }
}

通过putExtra()参数的键,获取数据。

image-20230717215403967

4、向上一个活动传递数据

startActivityForResult 的替代方案registerForActivityResult

4.1 设计思路

大致思路:先向下传递一个Intent,向下的activity操作这个Intent后再次将这个Intent返回给上一个activity。

image-20230718113337072

既然需要使用新的功能,那么我们就必须要先了解以下,刚说到的ActivityResultLauncherActivityResultContractActivityResultCallback到底是些什么东西

  • ActivityResultLauncher 从字面意思其实就能很好理解,可以理解它就是一个Activity的启动器,它的作用就是承载启动对象与返回对象,通registerForActivityResult返回该对象,这时并不会立即启动另一个Activity。
  • ActivityResultContract 是用来协定所需的输入类型以及结果的输出类型,Android默认提供了一些常用的定义,例如上面所使用到到ActivityResultContracts.StartActivityForResult()。当然这里你也可以通过继承ActivityResultContract实现自己的定义。
  • ActivityResultCallback 通过名字就可以了解到这是启动Activity并返回到当前Activity时的结果回调。

4.2 设计ActivityResultLauncher

根据上面的流程图我们可以知道首先先实现ActivityResultLauncher,java实现代码如下:

private ActivityResultLauncher<Intent> resultLauncher = registerForActivityResult(
    new ActivityResultContracts.StartActivityForResult(),
    new ActivityResultCallback<ActivityResult>() {
        @Override
        public void onActivityResult(ActivityResult result) {
            //判断是否传入正确的result
            if(result.getResultCode() == RESULT_OK){
                Intent intent = result.getData();   //获取上一个活动返回的Intent
                //判断上一个活动的Intent是否存在,存在则在日志中输入
                if(intent != null){
                    String str = intent.getStringExtra("data_return");
                    Log.d("DATA",str);
                }
            }
        }
    });

通过这段代码我们可以看到使用了registerForActivityResult这个方法,传递了两个参数。

4.2.1 registerForActivityResult() 方法解析

registerForActivityResult() 方法接收两个参数。

  • 第一个参数是一种 Contract 类型。

    Contract 用于指定一个 Activity 被调用时,使用 I 类型的输入,产生 O 类型的输出。

  • 第二个参数是回调。即当存在返回值时,处理返回结果的代码。用 lambda 表达式来实现

image-20230718114557356

在实现一个 Activity 向上一个 Activity 传递数据的需求中第一个参数可以传入 ActivityResultContracts.StartActivityForResult()该对象的 输入类型 I 为 Intent,输出类型 O 为 ActivityResult

4.3 向下传递Intent

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    ActivityMainBinding  activityMainBinding = ActivityMainBinding.inflate(getLayoutInflater());

    setContentView(activityMainBinding.getRoot());

    Button button = (Button) activityMainBinding.button1;
    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = new Intent(getApplicationContext(), SecondActivity.class);
            //向下传递Intent
            resultLauncher.launch(intent);
        }
    });
}

4.4 下一个活动接收Intent

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    ActivityMain2Binding binding = ActivityMain2Binding.inflate(getLayoutInflater());
    setContentView(binding.getRoot());

    View button = binding.button2;

    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            //获取前一个活动传递的Intent
            Intent intent = getIntent();
            //给这个Intent封装value
            intent.putExtra("data_return","xupt3G");
            //返回活动的结果
            setResult(RESULT_OK,intent);

            Toast.makeText(getApplicationContext(),"已经返回结果", Toast.LENGTH_SHORT).show();
            finish();
        }
    });
}

setResult()方法接收两个参数,第一个参数用于向上个活动返回处理结果,一般只使用RESULT OKRESULT_CANCELED这两个值,第二个参数则把带有数据的Intent传递回去。

image-20230718115455681

现在当我们返回上一个活动时就会正常返回值了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

摸鱼小小虫

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

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

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

打赏作者

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

抵扣说明:

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

余额充值