Rearrange ExternalResource.toAutoCloseable and update docs for ExternalResource

This commit is contained in:
Him188 2022-03-21 13:39:41 +00:00
parent 57a4b80d55
commit 4c600f9ded

View File

@ -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.
* ## 未释放资源的补救策略
*
* ## 实现 [ExternalResource]
* 2.7 , 每个 mirai 内置的 [ExternalResource] 实现都有引用跟踪, [ExternalResource] GC 后会执行被动释放.
* 这依赖于 JVM 垃圾收集策略, 因此不可靠, 资源仍然需要手动 close.
*
* ## 使用单次自动释放
*
* 若创建的资源仅需要*很快地*使用一次, 可使用 [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
///////////////////////////////////////////////////////////////////////////
}
/**