# Activity Results 总结和封装


### Activity Results 总结和封装

封装后的`API`很易用, 而且一看就知道是原理, 这还要总结啥, `kotlin` `lambda` yyds!

具体可以展开如下代码:

```kotlin
import android.content.Intent
import android.graphics.Bitmap
import android.net.Uri
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResult
import androidx.activity.result.ActivityResultCaller
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment

/**
 * Author zsqw123
 * Create by damyjy
 * Date 2021/7/10 13:38
 */

fun ActivityResultCaller.takePhoto(targetUri: Uri, callback: (Boolean) -> Unit) =
    registerForActivityResult(ActivityResultContracts.TakePicture(), callback).launch(targetUri)

fun ActivityResultCaller.takePhoto(callback: (Bitmap) -> Unit) =
    registerForActivityResult(ActivityResultContracts.TakePicturePreview(), callback).launch(null)

fun ActivityResultCaller.requestPermissions(vararg permissions: String, callback: (Map<String, Boolean>) -> Unit) =
    registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions(), callback).launch(permissions)

fun ActivityResultCaller.takeVideo(targetUri: Uri, callback: (Bitmap) -> Unit) =
    registerForActivityResult(ActivityResultContracts.TakeVideo(), callback).launch(targetUri)

fun ActivityResultCaller.pickContact(callback: (Uri) -> Unit) =
    registerForActivityResult(ActivityResultContracts.PickContact(), callback).launch(null)

fun ActivityResultCaller.getContent(mimeType: String, callback: (Uri) -> Unit) =
    registerForActivityResult(ActivityResultContracts.GetContent(), callback).launch(mimeType)

fun ActivityResultCaller.createDocument(defaultName: String, callback: (Uri) -> Unit) =
    registerForActivityResult(ActivityResultContracts.CreateDocument(), callback).launch(defaultName)

fun ActivityResultCaller.openDocuments(vararg mimeType: String, callback: (List<Uri>) -> Unit) =
    registerForActivityResult(ActivityResultContracts.OpenMultipleDocuments(), callback).launch(mimeType)

fun ActivityResultCaller.openDocument(vararg mimeType: String, callback: (Uri) -> Unit) =
    registerForActivityResult(ActivityResultContracts.OpenDocument(), callback).launch(mimeType)

fun ActivityResultCaller.openDocumentTree(defaultUri: Uri? = null, callback: (Uri) -> Unit) =
    registerForActivityResult(ActivityResultContracts.OpenDocumentTree(), callback).launch(defaultUri)

inline fun <reified C> ComponentActivity.startAndResult(vararg pairs: Pair<String, Any>, noinline callback: (ActivityResult) -> Unit) =
    registerForActivityResult(ActivityResultContracts.StartActivityForResult(), callback)
        .launch(Intent(this, C::class.java).apply { putExtras(bundleOf(*pairs)) })

inline fun <reified C> Fragment.startAndResult(vararg pairs: Pair<String, Any>, noinline callback: (ActivityResult) -> Unit) =
    registerForActivityResult(ActivityResultContracts.StartActivityForResult(), callback)
        .launch(Intent(context, C::class.java).apply { putExtras(bundleOf(*pairs)) })

```

什么? 你不知道如何获取一个文件的`mimeType`? 没关系, `Java`有自带方法的, 这里我做了包装

```kotlin
object typeMap {
    operator fun get(file: File): String = URLConnection.getFileNameMap().getContentTypeFor(file.name) ?: ""
    operator fun get(fileName: String): String = get(File(fileName))
}
```

使用起来极为舒适:

```kotlin
val mimeType = typeMap[name]
```

#### 哦？

你以为真的这么简单就你用了吗？没错，这种`API`看起来简单直白，大多数人可能都会认为官方应该是这么用的，但实际上当你运行后会报错如下：

```
java.lang.IllegalStateException: LifecycleOwner com.zsqw123.learner.other.permission.storage.StorageAct@1c344622 is attempting to register while current state is RESUMED. LifecycleOwners must call register before they are STARTED.
```

实际上这玩意他要求在使用之前先把回调搞好, 然后再去获取并`launch`

!!!很气愤 但是就这样结束了吗? 我会屈服吗? 怎么可能! 直接将全部事件加入`pending`中, 调用的时候修改`map`中的函数类型调用即可

```kotlin
val ActivityResultCaller.pendingResults: SparseArray<(Any) -> Unit> by lazy { SparseArray() }
val ActivityResultCaller.pendingLaunches: SparseArray<ActivityResultLauncher<*>> by lazy { SparseArray() }
```

而相对应的我们在调用对应的触发事件的函数的同时, 从`map`里面取出来进行一下`launch`操作即可:

```kotlin
fun ActivityResultCaller.takePhoto(callback: (Bitmap) -> Unit) {
    pendingResults[1] = { callback(it as Bitmap) }
    pendingLaunches[1].launch(null)
}
```

完整代码: [new-1-ActivityResults (github.com)](https://gist.github.com/zsqw123/0716896d89805af9e4704d909ecb26e5)




