刚刚看 I/O 直播时听到 Kotlin gets officially supported,真的蛮意外的。

Kotlin 的 killer-app 大约就是用来写 Android app 的 Anko。从我初次用 Anko 到现在,已经过去快一年了。遗憾的是在之前的公司里,由于各种各样的原因,一直没法在线上产品中使用 Kotlin。

直到我上个月换了工作后——刚刚结束的四月里,使用 Anko,在不到一个月里就写完了两个漂亮的 Android App 并上线,生产力和舒适度实在前所未有。

当然,由于我很长时间里的主要在写 JavaScript,于是确实习惯了使用 Promise。我于是就简短地用 Kotlin 写了一个 Promise 实现—— https://github.com/kmxz/Votive/。API 尽可能地接近 JavaScript 中的 Promise;只是所有 Promise 的名称都改成了 Votive。

譬如,将 Android 的运行时权限申请封装为 Promise,只需要这么一点 boilerplating:

const val REQUEST_CODE_MIN = 6910
const val REQUEST_CODE_MAX = 7910

open class BaseActivity: AppCompatActivity() {

    private var lastRequestCode = REQUEST_CODE_MIN

    private var permissionCallback = mutableMapOf<Int, Pair<(Unit) -> Unit, ((Unit) -> Unit)>>()

    fun withPermission(permission: String) = Votive<Unit, Unit> { resolve, reject ->
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
                val requestCode = lastRequestCode++
                if (lastRequestCode > REQUEST_CODE_MAX) { lastRequestCode = REQUEST_CODE_MIN }
                permissionCallbacks.put(requestCode, Pair(resolve, reject))
                ActivityCompat.requestPermissions(this, arrayOf(permission), requestCode)
            } else {
                resolve(Unit)
            }
        } else {
            resolve(Unit)
        }
    }

    final override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        if (requestCode in REQUEST_CODE_MIN..REQUEST_CODE_MAX) {
            val callback = permissionCallbacks.remove(requestCode)
            if (grantResults.all { it == PackageManager.PERMISSION_GRANTED }) {
                callback?.first?.invoke(Unit)
            } else { // already removed anyway
                callback?.second?.invoke(Unit)
            }
        } else {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        }
    }

}

就可以使用 Promise 风格去申请运行时权限:

withPermission(Manifest.permission.ACCESS_FINE_LOCATION)
    .thenSimple { Log.i(locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER)) }
    .catchSimple { alert("Don't give me permission? I'll crash") }

嗯,以及我现在越来越觉得我一个月前辞职实在是绝赞的决定。

此文同时发布于 https://zhuanlan.zhihu.com/p/26966006

标签: javascript, kotlin, promise

添加新评论