Есть ли какой-нибудь способ переопределить функцию суперкласса либо из функций расширения, либо из интерфейсов в kotlin?

#android #kotlin #kotlin-extension

#Android #kotlin #kotlin-расширение

Вопрос:

В Android для выполнения некоторых задач мы требуем от пользователя предоставления соответствующих разрешений. Полный процесс проверки и запроса разрешения включает в себя 3 шага: проверка разрешения, запрос разрешения и проверка результата. Если в разрешении отказано, тогда не нужно запускать эту задачу. Итак, чтобы упростить это, я написал следующий интерфейс и функцию расширения в ActivityExtensions.kt

 private val permissionTaskSource = HashMap<Int, TaskCompletionSource<Boolean>>()

interface PermissionHandler {
    @RequiresApi(Build.VERSION_CODES.M)
    fun Activity.permissionRequest(requestCode: Int, vararg permissions: String): Task<Boolean> {
        requestPermissions(permissions, requestCode)
        val tcs = TaskCompletionSource<Boolean>()
        permissionTaskSource[requestCode] = tcs
        return tcs.task
    }

    fun permissionResult(requestCode: Int, grantResults: IntArray) {
        permissionTaskSource[requestCode]!!.setResult(grantResults.all { it == PERMISSION_GRANTED })
        permissionTaskSource.remove(requestCode)
    }
}

suspend fun <T> T.requiresPermission(vararg permissions: String): Unit? where T : Activity, T : PermissionHandler {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
        return Unit   // If version lower than M then no need of runtime permissions.
    if (permissions.all { ContextCompat.checkSelfPermission(this, it) == PERMISSION_GRANTED })
        return Unit   // If already all permissions granted, then no need to ask again.

    val granted = permissionRequest(System.currentTimeMillis().toInt(), *permissions).await()
    if (granted)
        return Unit   // Permission granted now
    return null   // Permission denied now
}
 

Всякий раз, когда требуются некоторые разрешения для выполнения задачи в activity или fragment, я могу использовать эту строку:

 private suspend fun someTask() {
    requiresPermission(/* list of required permissions */) ?: run{ /*permission denied. handle properly*/ return }
    // Inside fragment this has to be called with requiresActivity() receiver.
    ...
}
 

Все это работает нормально.. но в каждом действии / фрагменте я должен написать эти 4 строки кода.

 override fun onRequestPermissionsResult(
    requestCode: Int, permissions: Array<out String>, grantResults: IntArray
) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    permissionResult(requestCode, grantResults)
}
 

Есть ли какой-нибудь способ переместить эти коды также в ActivityExtensions.kt файл, чтобы сделать его более аккуратным и избежать повторяющегося кода?

Комментарии:

1. Это не ответ, но теперь удобнее работать с разрешениями с помощью Android Results API (об этом хорошо написано здесь: wajahatkarim.com/2020/05/activity-results-api-onactivityresult ).

2. @SergeiMikhailovskii Нью-Йоркский ресурс.. Я пройду через это.. Спасибо 🙂

3. Я предпочитаю повторять этот код в каждом действии и избегать наследования… но с наследованием это нужно делать только в BaseActivity и расширяет этот класс в каждом действии.

4. @ManuelMato могу я узнать, почему вы предпочитаете повторять код вместо наследования? (кроме замены Activity на MyActivity везде выглядит некрасиво.)

5. Поскольку несколько действий (1,23?) Будут заключаться в проверке разрешения местоположения, поэтому BaseActivity опасен, потому что в будущем, возможно, функциональность будет расширяться с помощью другого поведения, поэтому я предпочитаю функцию расширения