将具有不同方法签名的不同函数作为 kotlin 中的参数传递给函数

Pass different functions with different method signatures to a function as a parameter in kotlin

我正在开发一个 android 应用程序,使用 kotlin 作为我的主要语言。我需要为应用程序的某些部分请求一些 运行 时间权限。因此,我没有编写类似的样板代码来请求权限,而是决定编写一个单独的静态函数来检查权限,并 运行 一个方法。这是静态函数

fun permissionExecution(childFragment: Fragment, permission: String, expression: ????) {

    Dexter.withActivity(childFragment.requireActivity())
        .withPermission(permission)
        .withListener(object : PermissionListener {
            override fun onPermissionGranted(response: PermissionGrantedResponse?) {
                expression()
            }

            override fun onPermissionRationaleShouldBeShown(
                permission: PermissionRequest?,
                token: PermissionToken
            ) {
                token.continuePermissionRequest()
            }

            override fun onPermissionDenied(response: PermissionDeniedResponse) {
                if(response.isPermanentlyDenied) {
                    openSettings(childFragment)
                }
            }

        }).check()
}

当我传入不带参数的方法时,这段代码运行良好。但在某些情况下,我想传递具有不同参数类型的方法。

  1. 像这样调用方法permissionExecution(childfragment, permission, foo(string))
  2. 像这样调用相同的方法permissionExecution(childfrgment, permission, bas(string, Int))

permissionExecution() 方法中的 espression 参数可以使用什么 class 类型

如果我理解正确的话,你已经实现了一个通用的静态函数来检查权限并向它传递一些 lambda,当权限被授予时将调用它。我不明白为什么你这些 lambda 需要一些参数参数。下面的实现是你想要的吗?

class CameraFragment {

  fun onCreateView() {
    permissionExecution(childFragment = arg1, permission = "perm", expression = {
      // open camera
    })
  }
}

class LocationActivity {
  fun onCreate() {
    permissionExecution(childFragment = arg1, permission = "perm", expression = {
      fetchLocation()
    })
  }

  fun fetchLocation() {
    // get location, do stuff
  }
}

在 lambda 变量的定义中包含函数参数没有意义。您已经拥有调用这些其他函数所需的一切:

permissionExecution(myFragment, Manifest.permission.RECORD_AUDIO) {
    foo(myString)
}

permissionExecution(myFragment, Manifest.permission.CAMERA) {
    bar(myString, myInt)
}

如果您需要 PermissionGrantedResponse 来确定这些参数是什么,您可以将其定义为函数输入:

fun permissionExecution(childFragment: Fragment, permission: String, expression: (PermissionGrantedResponse) -> Unit) {

    Dexter.withActivity(childFragment.requireActivity())
        .withPermission(permission)
        .withListener(object : PermissionListener {
            override fun onPermissionGranted(response: PermissionGrantedResponse) {
                expression(response)
            }
    //...
}

//...

permissionExecution(myFragment, Manifest.permission.RECORD_AUDIO) { response ->
    foo(response.permissionName)
}

这里有一个不太优雅的解决方案。我用这样的单一方法接口创建了一个包装器 class

class Permissions(val childFragment: Fragment, private val permission: String, val runExpression: RunExpression) {
interface RunExpression{
    fun expression()
}

fun permissionExecution() {

    Dexter.withActivity(childFragment.requireActivity())
        .withPermission(permission)
        .withListener(object : PermissionListener {
            override fun onPermissionGranted(response: PermissionGrantedResponse?) {
                runExpression.expression()
            }

            override fun onPermissionRationaleShouldBeShown(
                permission: PermissionRequest?,
                token: PermissionToken
            ) {
                token.continuePermissionRequest()
            }

            override fun onPermissionDenied(response: PermissionDeniedResponse) {
                if(response.isPermanentlyDenied) {
                    openSettings(childFragment)
                }
            }

        }).check()
}

}

然后每次我需要权限时都这样调用class

1.

Permissions(this, Manifest.permission.READ_CONTACTS, object : Permissions.RunExpression {
                override fun expression() {
                    startActivityForResult(intent, PICK_CONTACT)
                }
            }).permissionExecution()

2.

Permissions(this, Manifest.permission.READ_CONTACTS, object : Permissions.RunExpression {
                override fun expression() {
                    writeFileToLocation(file, locationPath)
                }
            }).permissionExecution()

我通过调整解决方案 找到的一个更好的方法是首先创建一个这样的界面

interface RunExpression{
fun expression()}

然后使用函数签名中的接口

fun permissionExecution(childFragment: Fragment, permission : String, runExpression: RunExpression) {

Dexter.withActivity(childFragment.requireActivity())
    .withPermission(permission)
    .withListener(object : PermissionListener {
        override fun onPermissionGranted(response: PermissionGrantedResponse?) {
            runExpression.expression()
        }

        override fun onPermissionRationaleShouldBeShown(
            permission: PermissionRequest?,
            token: PermissionToken
        ) {
            token.continuePermissionRequest()
        }

        override fun onPermissionDenied(response: PermissionDeniedResponse) {
            if(response.isPermanentlyDenied) {
                openSettings(childFragment)
            }
        }

    }).check()}

然后在我想调用函数的任何地方,我将实现接口的匿名对象保存到一个变量中

val startMyActivity = object : RunExpression {
            override fun expression() {
                startActivityForResult(intent, PICK_CONTACT)
            }
        }

然后用变量调用函数

permissionExecution(this, Manifest.permission.READ_CONTACTS, startMyActivity)