Discuz! BBS

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 135|回复: 3

private Intent intent详解

[复制链接]

347

主题

501

帖子

3066

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
3066
发表于 2025-8-27 21:42:27 | 显示全部楼层 |阅读模式
这句代码是 MainActivity 类中的一个成员变量声明,让我详细解释一下:
代码解析
  1. private Intent intent;
复制代码

1. 访问修饰符 private
表示这个变量只能在 MainActivity 类内部访问
外部类无法直接访问这个变量
符合封装原则,保护内部实现细节
2. 数据类型 Intent
Intent 是 Android 中用于组件间通信的重要类
可以用来启动 ActivityService,发送 Broadcast
在这里用于存储待启动的 Activity 信息
3. 变量名 intent
命名清晰表达了其用途:存储一个 Intent 对象
在 MainActivity 中的作用
1. 工作流程
这个变量在权限检查流程中起关键作用:
  1. // 1. 在点击按钮时保存目标 Intent
  2. private void isPrivacyConfirm(Intent i) {
  3.     boolean privacyConfirm = mSharedPreferences.getBoolean(SpeechApp.PRIVACY_KEY, false);
  4.     if (privacyConfirm) {
  5.         intent = i;  // 保存目标 Intent
  6.         mPermissionResult.launch(Manifest.permission.RECORD_AUDIO);  // 请求权限
  7.     }
  8. }

  9. // 2. 权限回调中使用保存的 Intent
  10. private ActivityResultLauncher<String> mPermissionResult = registerForActivityResult(
  11.         new ActivityResultContracts.RequestPermission(),
  12.         result -> {
  13.             if (result) {
  14.                 if (intent != null) {
  15.                     MainActivity.this.startActivity(intent);  // 启动之前保存的 Intent
  16.                 }
  17.                 SpeechApp.initializeMsc(MainActivity.this);
  18.             }
  19.         });
复制代码

2. 具体使用场景
在各个功能按钮的点击事件中:
  1. // 语音转写按钮
  2. findViewById(R.id.iatBtn).setOnClickListener(v -> {
  3.     // 保存要启动的 IatDemo Activity 的 Intent
  4.     isPrivacyConfirm(new Intent(MainActivity.this, IatDemo.class));
  5. });
复制代码

设计模式分析
1. 延迟启动模式
用户点击功能按钮时并不立即启动对应 Activity
先检查隐私政策和权限
权限授予后再启动目标 Activity
2. 中间变量作用
intent 变量作为"传递者",在权限检查方法和权限回调之间传递目标 Activity 信息
避免在权限回调中重复创建 Intent 对象
注意事项
1. 线程安全性
由于 Android UI 操作都在主线程进行,这里不需要考虑线程安全问题
2. 可能的改进
可以考虑使用局部变量传递,避免类成员变量
或者使用更现代的导航组件来管理页面跳转
这个变量虽然简单,但在实现权限检查和页面跳转的流程控制中起着关键的桥梁作用。
回复

使用道具 举报

347

主题

501

帖子

3066

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
3066
 楼主| 发表于 2025-8-27 21:52:29 | 显示全部楼层
  1. findViewById(R.id.iatBtn).setOnClickListener(v -> {
  2.             isPrivacyConfirm(new Intent(MainActivity.this, IatDemo.class));
  3.         });
复制代码

详解这部分new Intent(MainActivity.this, IatDemo.class)  :
这行代码创建了一个用于启动 IatDemo Activity 的 Intent 对象。让我详细解释每个部分:
  1. new Intent(MainActivity.this, IatDemo.class)
复制代码

1. new Intent()
这是创建 Intent 对象的构造函数调用。
2. MainActivity.this
这是第一个参数,表示当前的上下文(Context):
指向当前的 MainActivity 实例
在内部类或匿名类中,需要使用 MainActivity.this 来明确指定外部类实例
提供启动 Activity 所需的上下文信息
3. IatDemo.class
这是第二个参数,表示目标 Activity 的 Class 对象:
指定要启动的 Activity 类型
这是一个显式 Intent,明确指定了目标组件
Intent 构造函数详解
这个构造函数的签名是:
  1. public Intent(Context packageContext, Class<?> cls)
复制代码

参数说明:
packageContext: 启动 Activity 的上下文,这里使用 MainActivity.this
cls: 要启动的 Activity 的 Class 对象,这里是 IatDemo.class
在 MainActivity 中的完整流程
1. 用户点击按钮触发事件
  1. // 语音转写按钮点击事件
  2. findViewById(R.id.iatBtn).setOnClickListener(v -> {
  3.     isPrivacyConfirm(new Intent(MainActivity.this, IatDemo.class));
  4. });
复制代码


2. isPrivacyConfirm() 方法处理
  1. private void isPrivacyConfirm(Intent i) {
  2.     boolean privacyConfirm = mSharedPreferences.getBoolean(SpeechApp.PRIVACY_KEY, false);
  3.     if (privacyConfirm) {
  4.         intent = i;  // 保存这个 Intent 对象到成员变量
  5.         mPermissionResult.launch(Manifest.permission.RECORD_AUDIO);  // 请求录音权限
  6.     }
  7. }
复制代码

3. 权限请求完成后使用保存的 Intent
  1. private ActivityResultLauncher<String> mPermissionResult = registerForActivityResult(
  2.         new ActivityResultContracts.RequestPermission(),
  3.         result -> {
  4.             if (result) {
  5.                 if (intent != null) {
  6.                     // 使用之前保存的 Intent 启动 IatDemo Activity
  7.                     MainActivity.this.startActivity(intent);
  8.                 }
  9.                 SpeechApp.initializeMsc(MainActivity.this);
  10.             }
  11.         });
复制代码


Intent 的作用
这个 Intent 对象的作用是:
指定目标组件:明确要启动 IatDemo Activity
携带上下文:提供启动 Activity 所需的上下文信息
传递参数(如果需要):虽然这里没有额外参数,但 Intent 可以携带数据到目标 Activity
Android Activity 启动机制
这种显式 Intent 的工作原理:
Android 系统根据 IatDemo.class 找到对应的 Activity 组件
系统验证目标 Activity 是否在 AndroidManifest.xml 中声明
系统创建 IatDemo 实例并调用其生命周期方法
用户界面切换到 IatDemo 页面
总结来说,这行代码创建了一个用于启动语音转写功能页面(IatDemo)的意图对象,它是整个页面导航流程的起点
回复

使用道具 举报

347

主题

501

帖子

3066

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
3066
 楼主| 发表于 2025-8-27 22:03:03 | 显示全部楼层
  1. mPermissionResult.launch(Manifest.permission.RECORD_AUDIO);
复制代码

详解launch, 它带的参数传给谁了

launch 是 ActivityResultLauncher 类的方法,用于启动一个活动(Activity)并等待结果。让我详细解释一下:
  1. mPermissionResult.launch(Manifest.permission.RECORD_AUDIO);
复制代码

1. mPermissionResult
这是通过 registerForActivityResult 注册的 ActivityResultLauncher 对象,专门用于请求权限。
2. launch() 方法
这是启动操作的方法,参数会传递给对应的 ActivityResultContract。
3. 参数 Manifest.permission.RECORD_AUDIO
这是请求的权限:录音权限。
工作原理
1. 注册过程
  1. private ActivityResultLauncher<String> mPermissionResult = registerForActivityResult(
  2.     new ActivityResultContracts.RequestPermission(),  // Contract
  3.     result -> {  // Callback
  4.         if (result) {
  5.             if (intent != null) {
  6.                 MainActivity.this.startActivity(intent);
  7.             }
  8.             SpeechApp.initializeMsc(MainActivity.this);
  9.         }
  10.     });
复制代码

2. 参数传递流程
1)launch() 方法接收参数 Manifest.permission.RECORD_AUDIO
2)参数传递给 ActivityResultContracts.RequestPermission 这个 contract
3)Contract 处理参数并启动系统权限请求界面
4)用户操作后,系统返回结果给 callback

3. RequestPermission Contract 的处理
ActivityResultContracts.RequestPermission 内部会这样处理参数
  1. // 简化的内部实现
  2. public class RequestPermission extends ActivityResultContract<String, Boolean> {
  3.     @Override
  4.     public Intent createIntent(Context context, String permission) {
  5.         // 将权限字符串转换为请求权限的 Intent
  6.         return new Intent(context, RequestPermissionActivity.class)
  7.                 .putExtra("permission", permission);
  8.     }
  9.    
  10.     @Override
  11.     public Boolean parseResult(int resultCode, Intent intent) {
  12.         // 解析权限请求结果,返回布尔值
  13.         return resultCode == Activity.RESULT_OK;
  14.     }
  15. }
复制代码


完整流程
1、用户点击按钮:
  1. findViewById(R.id.iatBtn).setOnClickListener(v -> {
  2.     isPrivacyConfirm(new Intent(MainActivity.this, IatDemo.class));
  3. });
复制代码

2、检查隐私和启动权限请求:
  1. private void isPrivacyConfirm(Intent i) {
  2.     boolean privacyConfirm = mSharedPreferences.getBoolean(SpeechApp.PRIVACY_KEY, false);
  3.     if (privacyConfirm) {
  4.         intent = i;
  5.         // 传递录音权限参数给 RequestPermission contract
  6.         mPermissionResult.launch(Manifest.permission.RECORD_AUDIO);
  7.     }
  8. }
复制代码

3、系统处理权限请求:
系统显示权限请求对话框
用户选择允许或拒绝

4、回调处理结果
  1. registerForActivityResult(
  2.             new ActivityResultContracts.RequestPermission(),
  3. result -> {
  4.     if (result) {  // result 是 Boolean 类型,表示权限是否被授予
  5.         if (intent != null) {
  6.             MainActivity.this.startActivity(intent);  // 启动之前保存的 Intent
  7.         }
  8.         SpeechApp.initializeMsc(MainActivity.this);
  9.     }
  10. }
复制代码

launch() 方法的参数 Manifest.permission.RECORD_AUDIO 最终传递给了:
1)ActivityResultContracts.RequestPermission contract
2)该 contract 使用这个参数构建权限请求界面
3)用户操作后,contract 解析结果并传递给注册时提供的 callback

这种设计模式实现了关注点分离,让开发者只需关注业务逻辑,而不用处理复杂的 Activity 结果处理代码。

回复

使用道具 举报

347

主题

501

帖子

3066

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
3066
 楼主| 发表于 2025-8-27 22:16:16 | 显示全部楼层
  1. private ActivityResultLauncher<String> mPermissionResult = registerForActivityResult(
复制代码

中为什么要用<String> :
在 private ActivityResultLauncher<String> mPermissionResult = registerForActivityResult( 中使用 <String> 是因为 Java 的泛型机制,让我详细解释
1. ActivityResultLauncher<String>
这是泛型类的声明,其中 <String> 指定了类型参数:
ActivityResultLauncher 是一个泛型类
<String> 表示这个 launcher 处理的输入参数类型是 String
对应到实际使用中,就是权限名称(如 Manifest.permission.RECORD_AUDIO)
2. 为什么是 String 类型?
因为使用的是 ActivityResultContracts.RequestPermission 这个 contract:
  1. // RequestPermission contract 的定义
  2. public final class RequestPermission extends ActivityResultContract<String, Boolean> {
  3.     @Override
  4.     public Intent createIntent(@NonNull Context context, @NonNull String input) {
  5.         // input 参数是 String 类型,代表权限名称
  6.         // ...
  7.     }
  8.    
  9.     @Override
  10.     public Boolean parseResult(int resultCode, @Nullable Intent intent) {
  11.         // 返回 Boolean 类型的结果
  12.         // ...
  13.     }
  14. }
复制代码

3. 泛型参数对应关系
ActivityResultContract<I, O> 有两个泛型参数:
I (Input): 输入参数类型 - 对应 ActivityResultLauncher<I>
O (Output): 输出结果类型 - 对应回调函数的参数类型
对于 RequestPermission:
输入类型 I = String (权限名称)
输出类型 O = Boolean (是否授权)
完整的类型匹配:
  1. // registerForActivityResult 方法签名
  2. @NonNull
  3. public final <I, O> ActivityResultLauncher<I> registerForActivityResult(
  4.         @NonNull ActivityResultContract<I, O> contract,
  5.         @NonNull ActivityResultCallback<O> callback) {
  6.     // ...
  7. }

  8. // 使用时的类型推断
  9. ActivityResultLauncher<String> mPermissionResult = registerForActivityResult(
  10.     new ActivityResultContracts.RequestPermission(),  // ActivityResultContract<String, Boolean>
  11.     result -> {  // ActivityResultCallback<Boolean>,result 是 Boolean 类型
  12.         // ...
  13.     }
  14. );
复制代码


其他 Contract 的示例
为了更好地理解,这里给出其他 contract 的泛型使用示例:
  1. // 启动 Activity 并获取结果
  2. ActivityResultLauncher<Intent> activityLauncher = registerForActivityResult(
  3.     new ActivityResultContracts.StartActivityForResult(),  // ActivityResultContract<Intent, ActivityResult>
  4.     result -> {  // result 是 ActivityResult 类型
  5.         // 处理 Activity 结果
  6.     }
  7. );

  8. // 请求多个权限
  9. ActivityResultLauncher<String[]> multiplePermissionLauncher = registerForActivityResult(
  10.     new ActivityResultContracts.RequestMultiplePermissions(),  // ActivityResultContract<String[], Map<String, Boolean>>
  11.     result -> {  // result 是 Map<String, Boolean> 类型
  12.         // 处理多个权限请求结果
  13.     }
  14. );
复制代码

总结
使用 <String> 是因为:
RequestPermission contract 需要一个 String 类型的权限名称作为输入参数
Java 泛型机制要求在声明时指定具体类型
这样可以提供编译时类型检查,避免运行时类型错误
确保 launch() 方法只能传入 String 类型的参数
这种设计使得 API 更加类型安全和易于使用。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|DiscuzX

GMT+8, 2025-9-18 00:54 , Processed in 0.018296 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表