Browse Source

Rearrange `ExternalResource.toAutoCloseable` and update docs for ExternalResource

Him188 4 years ago
parent
commit
4c600f9ded
1 changed files with 65 additions and 35 deletions
  1. 65 35
      mirai-core-api/src/commonMain/kotlin/utils/ExternalResource.kt

+ 65 - 35
mirai-core-api/src/commonMain/kotlin/utils/ExternalResource.kt

@@ -40,13 +40,35 @@ import kotlin.contracts.contract
  *
  * [ExternalResource] 在创建之后就应该保持其属性的不变, 即任何时候获取其属性都应该得到相同结果, 任何时候打开流都得到的一样的数据.
  *
- * ## 创建
+ * # 创建
  * - [File.toExternalResource]
  * - [RandomAccessFile.toExternalResource]
  * - [ByteArray.toExternalResource]
  * - [InputStream.toExternalResource]
  *
- * ### 在 Java 获得和使用 [ExternalResource] 实例
+ * ## 在 Kotlin 获得和使用 [ExternalResource] 实例
+ *
+ * ```
+ * file.toExternalResource().use { resource -> // 安全地使用资源
+ *     contact.uploadImage(resource) // 用来上传图片
+ *     contact.files.uploadNewFile("/foo/test.txt", file) // 或者用来上传文件
+ * }
+ * ```
+ *
+ * 注意, 若使用 [InputStream], 必须手动关闭 [InputStream]. 一种使用情况示例:
+ *
+ * ```
+ * inputStream.use { input -> // 安全地使用 InputStream
+ *     input.toExternalResource().use { resource -> // 安全地使用资源
+ *         contact.uploadImage(resource) // 用来上传图片
+ *         contact.files.uploadNewFile("/foo/test.txt", file) // 或者用来上传文件
+ *     }
+ * }
+ * ```
+ *
+ * 注意, 若使用 [InputStream], 必须手动关闭 [InputStream]. 一种使用情况示例:
+ *
+ * ## 在 Java 获得和使用 [ExternalResource] 实例
  *
  * ```
  * try(ExternalResource resource = ExternalResource.create(file)) { // 使用文件 file
@@ -57,23 +79,39 @@ import kotlin.contracts.contract
  *
  * 注意, 若使用 [InputStream], 必须手动关闭 [InputStream]. 一种使用情况示例:
  *
- * ```
- * try(InputStream stream = ...) {
- *     try(ExternalResource resource = ExternalResource.create(stream)) {
+ * ```java
+ * try(InputStream stream = ...) { // 安全地使用 InputStream
+ *     try(ExternalResource resource = ExternalResource.create(stream)) { // 安全地使用资源
  *         contact.uploadImage(resource); // 用来上传图片
  *         contact.files.uploadNewFile("/foo/test.txt", file); // 或者用来上传文件
  *     }
  * }
  * ```
  *
- * ## 释放
+ * # 释放
  *
  * 当 [ExternalResource] 创建时就可能会打开一个文件 (如使用 [File.toExternalResource]).
  * 类似于 [InputStream], [ExternalResource] 需要被 [关闭][close].
  *
- * 自 2.7 起, 每个 mirai 内置的 [ExternalResource] 实现都有引用跟踪, 当 [ExternalResource] 被 GC 后会执行被动释放, 但是该策略并不代表不需要手动 close.
+ * ## 未释放资源的补救策略
+ *
+ * 自 2.7 起, 每个 mirai 内置的 [ExternalResource] 实现都有引用跟踪, 当 [ExternalResource] 被 GC 后会执行被动释放.
+ * 这依赖于 JVM 垃圾收集策略, 因此不可靠, 资源仍然需要手动 close.
  *
- * ## 实现 [ExternalResource]
+ * ## 使用单次自动释放
+ *
+ * 若创建的资源仅需要*很快地*使用一次, 可使用 [toAutoCloseable] 获得在使用一次后就会自动关闭的资源.
+ *
+ * 示例:
+ * ```java
+ * contact.uploadImage(ExternalResource.create(file).toAutoCloseable()); // 创建并立即使用单次自动释放的资源
+ * ```
+ *
+ * **注意**: 如果仅使用 [toAutoCloseable] 而不通过 [Contact.uploadImage] 等 mirai 内置方法使用资源, 资源仍然会处于打开状态且不会被自动关闭.
+ * 最终资源会由上述*未释放资源的补救策略*关闭, 但这依赖于 JVM 垃圾收集策略而不可靠.
+ * 因此建议在创建单次自动释放的资源后就尽快使用它, 否则仍然需要考虑在正确的时间及时关闭资源.
+ *
+ * # 实现 [ExternalResource]
  *
  * 可以自行实现 [ExternalResource]. 但通常上述创建方法已足够使用.
  *
@@ -175,6 +213,25 @@ public interface ExternalResource : Closeable {
      */
     public val origin: Any? get() = null
 
+    /**
+     * 创建一个在 _使用一次_ 后就会自动 [close] 的 [ExternalResource].
+     *
+     * @since 2.8.0
+     */
+    public fun toAutoCloseable(): ExternalResource {
+        return if (isAutoClose) this else {
+            val delegate = this
+            object : ExternalResource by delegate {
+                override val isAutoClose: Boolean get() = true
+                override fun toString(): String = "ExternalResourceWithAutoClose(delegate=$delegate)"
+                override fun toAutoCloseable(): ExternalResource {
+                    return this
+                }
+            }
+        }
+    }
+
+
     public companion object {
         /**
          * 在无法识别文件格式时使用的默认格式名. "mirai".
@@ -554,33 +611,6 @@ public interface ExternalResource : Closeable {
         }
         // endregion
     }
-
-    ///////////////////////////////////////////////////////////////////////////
-    // region Java Friendly Functions
-    ///////////////////////////////////////////////////////////////////////////
-
-    /**
-     * 创建一个在 _使用一次_ 后就会自动 [close] 的 [ExternalResource].
-     *
-     * @since 2.8.0
-     */
-    public fun toAutoCloseable(): ExternalResource {
-        return if (isAutoClose) this else {
-            val delegate = this
-            object : ExternalResource by delegate {
-                override val isAutoClose: Boolean get() = true
-                override fun toString(): String = "ExternalResourceWithAutoClose(delegate=$delegate)"
-                override fun toAutoCloseable(): ExternalResource {
-                    return this
-                }
-            }
-        }
-    }
-
-    ///////////////////////////////////////////////////////////////////////////
-    // endregion
-    ///////////////////////////////////////////////////////////////////////////
-
 }
 
 /**