Search code examples
androidkotlinlistenerreturn-value

Return a value from a Listeners onSuccess() in Kotlin (Android)


I try these tutorials: https://github.com/docusign/mobile-android-sdk/blob/master/README.md, especially the function getUserSignatureInfo. In this function a REST API call (userSignaturesGetUserSignature) is made.

In my code below I try to return a value (userSignatureId) I get from REST API. I understand, it's impossible this way, because onSuccess() will be invoked later as the outer function getUserSignatureInfo() returns.

I want to call getUserSignatureInfo() from a Fragments onActivityCreated() and use this value on creating a RecyclerView.Adapter.

The question is, what is the (best practice) way to do something like this: make a REST API call, wait for response, and use the response in further code.

// my Fragment
...
...
val userSignatureId = getUserSignatureInfo()
recyclerView.adapter = createMyAdapter(userSignatureId)
...
...



// function where the REST API call is made
fun getUserSignatureInfo(context: Context) : String {
    val eSignApiDelegate = DocuSign.getInstance().getESignApiDelegate()
    val usersApi = eSignApiDelegate.createApiService(UsersApi::class.java)

    val authDelegate = DocuSign.getInstance().getAuthenticationDelegate()
    val user = authDelegate.getLoggedInUser(context)

    var userSignatureId = ""

    eSignApiDelegate.invoke(object : DSESignApiListener {

        override fun <T> onSuccess(response: T?) {
            if (response is UserSignaturesInformation) {
                val userSignature = (response as UserSignaturesInformation).getUserSignatures().get(0)
                Log.d(TAG, "Signature Id: " + userSignature.signatureId);

                // My problem: this assignment is useless 
                // because the outer function getUserSignatureInfo()
                // returns earlier as onSuccess()
                userSignatureId = userSignature.signatureId
            }
        }

        override fun onError(exception: DSRestException) {
            // TODO: Handle error
        }
    }) {
        usersApi!!.userSignaturesGetUserSignature(user.accountId, user.userId, "signature")
    }
    
    // This is my problem: userSignatureId is empty because 
    // onSuccess() fires later as this function returns  
    return userSignatureId
} 

Thank you much!


Solution

  • You could pass a callback into getUserSignatureInfo(), for example

    fun getUserSignatureInfo(context: Context, callback: (String)->Unit) : String {
        val eSignApiDelegate = DocuSign.getInstance().getESignApiDelegate()
        val usersApi = eSignApiDelegate.createApiService(UsersApi::class.java)
    
        val authDelegate = DocuSign.getInstance().getAuthenticationDelegate()
        val user = authDelegate.getLoggedInUser(context)
    
    
        eSignApiDelegate.invoke(object : DSESignApiListener {
    
            override fun <T> onSuccess(response: T?) {
                if (response is UserSignaturesInformation) {
                    val userSignature = (response as UserSignaturesInformation).getUserSignatures().get(0)
                    Log.d(TAG, "Signature Id: " + userSignature.signatureId);
    
                    // return the value in the callback
                    callback(userSignature.signatureId)
    
                }
            }
    

    When you want to use the string value from another class,

    getUserSignatureInfo(context) { id ->
      Log.d("test", id)
    }