# 电子野簿 **Repository Path**: limry/electronic-field-book ## Basic Information - **Project Name**: 电子野簿 - **Description**: 不成熟的,凑合用 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-07-05 - **Last Updated**: 2025-07-05 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README context可以简单的理解为android环境,某些代码在Android环境下才能用,就要传一个对象过去 ![image-20250621005225640](C:\Users\lmr\AppData\Roaming\Typora\typora-user-images\image-20250621005225640.png) 在这段代码中,`permissionLauncher` 是通过 `registerForActivityResult` 注册的一个用于请求多个权限并处理回调的发射器。它的回调逻辑是这样的: ### 权限请求的发起 当调用 `permissionLauncher.launch(new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.CAMERA})` 时,系统会弹出一个权限请求对话框,让用户决定是否授予 `ACCESS_FINE_LOCATION` 和 `CAMERA` 这两个权限。 ### 权限请求结果的回调 当用户对权限请求做出响应后,`registerForActivityResult` 注册的回调函数就会被触发,`permissions` 参数是一个 `Map` 类型的对象,其中键是权限名称,值是对应的授权状态(`true` 表示授权,`false` 表示拒绝授权)。 ### 回调逻辑 1. **获取权限授权状态** - `boolean locationGranted = permissions.getOrDefault(Manifest.permission.ACCESS_FINE_LOCATION, false);`:尝试从 `permissions` 地图中获取 `ACCESS_FINE_LOCATION` 权限的授权状态,如果获取不到则默认为 `false`。 - `boolean cameraGranted = permissions.getOrDefault(Manifest.permission.CAMERA, false);`:同样尝试获取 `CAMERA` 权限的授权状态,获取不到则默认为 `false`。 2. **根据授权状态执行相应操作** - 如果 `locationGranted` 为 `true`,即用户授予了定位权限,则调用 `getGpsLocation()` 方法,假设该方法用于获取设备的 GPS 位置信息。 - 如果 `cameraGranted` 为 `true`,即用户授予了相机权限,则调用 `takePhoto()` 方法,假设该方法用于打开相机进行拍照。 - 如果两个权限都没有被授予,就弹出一个吐司提示用户 “需要定位和相机权限”,告知用户当前功能无法正常运行,因为缺少必要的权限。 ### 1. `registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), permissions)` 这是注册一个用于请求多个权限并处理结果的回调。 - **`ActivityResultContracts.RequestMultiplePermissions()`**:它是一个合同(Contract),用来定义你想要执行的操作类型,这里是请求多个权限。简单来说,它告诉系统:“我接下来要进行一个请求多个权限的操作,你帮我处理好和用户的交互,然后把结果返回给我”。 - **`permissions`**:这是回调函数的参数。当用户对权限请求做出回应后(允许或拒绝),系统会把权限请求的结果以一种特定的数据结构(`Map`)传递给这个回调函数,`permissions` 就代表这个结果数据。你可以把它理解为一个装着用户对每个权限请求回应的“篮子”,每个权限对应一个布尔值(`true` 表示允许,`false` 表示拒绝)。 ### 2. `permissions.getOrDefault(Manifest.permission.CAMERA, false)` 这是在权限结果的“篮子”里获取特定权限的授权状态。 - **`permissions.getOrDefault(Key, Default Value)`**:这是从 `permissions` 这个“篮子”(实际是一个映射关系,也就是 `Map`)里根据键(`Key`)获取对应的值(权限状态)。如果找不到对应的键,就返回一个默认值(`Default Value`)。 - **`Manifest.permission.CAMERA`**:这是键,代表相机权限。你是在问:“用户是否允许了相机权限呀?” 在这个“篮子”里查找对应的答案。 - **`false`**:默认值。如果在“篮子”里找不到 `Manifest.permission.CAMERA` 这个键对应的值(比如用户没有被问到这个权限,或者这个权限请求出现了问题没有返回结果),就默认认为这个权限是没有被允许的(`false`)。 ### 举个例子 假设你请求了定位权限和相机权限,用户允许了定位权限,拒绝了相机权限,那么 `permissions` 这个“篮子”里就会有两个键值对: - `Manifest.permission.ACCESS_FINE_LOCATION: true`(允许定位权限) - `Manifest.permission.CAMERA: false`(拒绝相机权限) 当你调用 `permissions.getOrDefault(Manifest.permission.CAMERA, false)`,它就会从这个“篮子”里找到 `Manifest.permission.CAMERA` 对应的值 `false` 并返回。 如果你请求的权限中没有相机权限,或者权限结果返回时出现了问题,这个“篮子”里就没有 `Manifest.permission.CAMERA` 这个键,那么 `getOrDefault` 就会返回默认值 `false`,也就是认为相机权限没有被允许。 这样设计可以避免在权限结果中找不到某个权限时程序出错,因为如果没有默认值,可能会出现空指针异常等问题。 ActivityResultLauncher:处理动作任务(Intent),等动作结果(比如照片)。 - 第一种 `Intent` 跳转的目标是启动一个你应用内的 `Activity`,所以直接指定目标类。 - 第二种 `Intent` 的目标是调用系统相机进行拍照,这是一个系统功能,它使用标准的动作(`MediaStore.ACTION_IMAGE_CAPTURE`)来请求系统服务。 1. - 第一种 `Intent` 通常不涉及从目标 `Activity` 返回数据,除非你特意实现返回数据的机制(如使用 `startActivityForResult` 系列方法)。 - 第二种 `Intent` 涉及从系统相机返回拍照得到的数据(例如照片),所以需要使用 `ActivityResultLauncher` 来处理返回的结果。 ActivityResultLauncher:处理权限请求(String[]),等用户回答。 Intent 是“去干啥”的信封(拍照片、跳页面)。 String[] 是“要啥权限”的清单(定位、相机)。 // 在 onCreate Button btnTest = findViewById(R.id.btn_test); btnTest.setOnClickListener(v -> { if (!ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)) { permissionLauncher.launch(new String[]{Manifest.permission.CAMERA}); Toast.makeText(this, "问相机权限", Toast.LENGTH_SHORT).show(); } else { cameraLauncher.launch(new Intent(MediaStore.ACTION_IMAGE_CAPTURE)); Toast.makeText(this, "开相机", Toast.LENGTH_SHORT).show(); } }); ## **最后再说一遍** ### `permissionLauncher` 和 `permissions` 的关系 `permissionLauncher` 是一个 `ActivityResultLauncher` 的实例,用于发起权限请求并接收用户对权限请求的响应。而 `permissions` 是在 `permissionLauncher` 的回调函数中传递的参数,它是一个 `Map` 类型的对象,表示用户对权限请求的响应结果。 **请求权限** :当你的应用需要访问某些受保护的功能(如定位、相机、麦克风等)时,**调用 `permissionLauncher.launch` 方法向用户请求权限**。用户做出选择后,系统会将结果传递给 `permissionLauncher` 注册的回调函数,你可以在回调中根据用户的响应执行相应的操作。 具体来说: 1. **`permissionLauncher` 的作用**: - 用于发起权限请求。 - 通过 `registerForActivityResult` 注册,指定权限请求的合同(`ActivityResultContracts.RequestMultiplePermissions`)和回调函数。 ```java ActivityResultLauncher permissionLauncher = registerForActivityResult( new ActivityResultContracts.RequestMultiplePermissions(), permissions -> { // 处理权限请求结果 }); ``` 2. **`permissions` 的作用**: - 在权限请求的回调函数中,`permissions` 是一个 `Map` 类型的参数,表示用户对每个权限请求的响应。 - 键是权限名称(如 `Manifest.permission.ACCESS_FINE_LOCATION`),值是布尔值,表示权限是否被授予。 ```java permissionLauncher.launch(new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.CAMERA}); ``` 当用户对权限请求做出响应后,`permissions` 会包含用户对每个权限的授权状态: ```java boolean locationGranted = permissions.getOrDefault(Manifest.permission.ACCESS_FINE_LOCATION, false); boolean cameraGranted = permissions.getOrDefault(Manifest.permission.CAMERA, false); ``` ### 使用示例 以下是一个完整的示例,展示如何使用 `permissionLauncher` 请求权限并处理响应: ```java // 注册权限请求的回调 ActivityResultLauncher permissionLauncher = registerForActivityResult( new ActivityResultContracts.RequestMultiplePermissions(), permissions -> { boolean locationGranted = permissions.getOrDefault(Manifest.permission.ACCESS_FINE_LOCATION, false); boolean cameraGranted = permissions.getOrDefault(Manifest.permission.CAMERA, false); //映射中获取定位权限的授权状态。如果找不到该权限,默认返回 false(表示权限未授予 if (locationGranted && cameraGranted) { // 同时获取定位和相机权限 getGpsLocationAndTakePhoto(); } else if (locationGranted) { // 仅获取定位权限 getGpsLocation(); } else if (cameraGranted) { // 仅获取相机权限 takePhoto(); } else { // 没有获取到任何权限 Toast.makeText(this, "需要定位和相机权限", Toast.LENGTH_SHORT).show(); } }); // 请求权限 permissionLauncher.launch(new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.CAMERA}); ``` ### 注意事项 - **权限检查**:在请求权限之前,最好先检查是否已经授予了权限,避免不必要的权限请求对话框。可以使用 `ContextCompat.checkSelfPermission` 进行检查。 - **权限请求时机**:选择合适的时机请求权限,通常在用户需要使用相关功能时才请求,以提高用户体验。 - **权限拒绝处理**:如果用户拒绝了权限,可以适当提示用户权限对于功能的重要性,但不要频繁弹出权限请求对话框。 通过以上方式,可以有效地使用 `permissionLauncher` 来请求权限,并通过 `permissions` 获取用户对权限的响应结果。 没错,从传统的数据库操作来看,`DAO`(Data Access Object,数据访问对象)通常负责处理数据库的连接以及具体的数据库操作,它起到了业务逻辑层与数据库之间的桥梁作用。而在 Android 的 Room 持久库中,`DAO`、`Entity`(实体类)和 `Database`(数据库类)这三者相互协作,共同完成了对数据库的访问和操作,它们之间的关系和协作方式如下: ### 1. `Entity`(实体类) - **作用**:定义了数据库表的结构,它是 Java 对象与数据库表之间的映射。一个实体类通常对应数据库中的一个表,实体类中的字段对应表中的列。 - **示例**: ```java @Entity(tableName = "users") public class User { @PrimaryKey(autoGenerate = true) public int id; public String name; public int age; public User(String name, int age) { this.name = name; this.age = age; } } ``` 在这个例子中,`User` 类对应数据库中的 `users` 表,`id` 字段对应表的主键列,`name` 和 `age` 字段分别对应表中的 `name` 和 `age` 列。 ### 2. `DAO`(数据访问对象) - **作用**:负责定义所有与数据库相关的操作方法,如插入、删除、更新和查询等。`DAO` 是一个接口或者抽象类,Room 会根据接口中的方法定义自动生成实现代码。 - **示例**: ```java @Dao public interface UserDao { @Insert void insert(User user); @Query("SELECT * FROM users") List getAllUsers(); } ``` 这里定义了一个 `UserDao` 接口,其中的 `insert` 方法用于向数据库插入一个 `User` 对象,`getAllUsers` 方法用于查询 `users` 表中的所有记录并返回一个 `User` 对象的列表。 ### 3. `Database`(数据库类) - **作用**:是 Room 数据库的抽象表示,负责管理数据库的版本和生命周期。它需要指定数据库中包含的实体类和 `DAO` 接口,并且通过它来获取 `DAO` 的实例。 - **示例**: ```java @Database(entities = {User.class}, version = 1) public abstract class AppDatabase extends RoomDatabase { public abstract UserDao userDao(); } ``` `AppDatabase` 是一个抽象类,它继承自 `RoomDatabase`,通过 `@Database` 注解指定了数据库包含的实体类(这里是 `User`)和数据库的版本号(这里是 1)。`userDao` 方法用于获取 `UserDao` 的实例。 ### 三者协作流程 1. **定义实体类**:先定义一个或多个实体类来表示数据库中的表结构。 2. **创建 DAO 接口**:接着创建一个 DAO 接口,使用注解来定义各种数据库操作方法。 3. **构建数据库类**:然后创建一个数据库类,这个类继承自 `RoomDatabase`,并使用 `@Database` 注解来指定实体类和数据库版本,同时声明 DAO 的访问方法。 4. **初始化数据库**:在应用中通过 `Room.databaseBuilder()` 或 `Room.inMemoryDatabaseBuilder()` 方法来创建数据库的实例。 5. **获取 DAO 并操作数据库**:通过数据库实例获取 DAO 的实例,然后调用 DAO 中定义的方法来执行具体的数据库操作。 这种架构设计使得数据访问层更加清晰和可维护,同时也简化了数据库操作的实现。 ```java List records = db.fieldNotebookDao().findByIdRange(); if (!records.isEmpty()) { for (FieldNotebookEntity record : records) { // 处理查询结果 } } else { // 没有找到符合条件的记录 } ```