1 year ago

#362148

test-img

LeeBaeng

what is Best practices for designing asynchronous task in this case( in kotlin, coroutine or thread)

my android app need to call more than 10 APIs at the same time. this call api's is use other library it made in other teams and result receive by listener in JsonString format.

this multiple calling api is need to call at same time. Because it takes a lot of time to call one API

i made it by callback structure like this. but i hope refactor this code covert to coroutine.

    private val library : OtherLibrary = OtherLibrary()
    private val retryCount: HashMap<String?, Int> = HashMap()
    private val listener = object : ApiListener {
        override fun onSucceeded(apiName: String, result: String?) {
            when (apiName) {
                "UserInfo" -> handleResultUserInfo(result)
                "ProductInfo" -> handleResultProductInfo(result)
                "....Info" -> handleResult___Info(result)
                // ... and Others
            }
        }
        override fun onUpdate(apiName: String, version: String) = library.callApi(apiName, this)
        override fun onFailed(apiName: String) = retry(apiName, this)
    }

    fun start() {
        callAPI("UserInfo")
        callAPI("ProductInfo")
        // ... and Others
    }

    fun callAPI(apiName: String, listener: ApiListener? = null) {
        val listener = listener ?: this.listener
        retryCount[apiName] = 0
        library.callApi(apiName, listener)
    }

    fun retry(apiName: String, listener: ApiListener) {
        if (retryCount[apiName]!! < 3) {
            retryCount[apiName]!!.plus(1)
            library.callApi(apiName, listener)
        }else{
            throw RuntimeException("API Call Failed: $apiName")
        }
    }

    fun handleResultUserInfo(result: String?) {
        // TODO parse & do something
    }

    fun handleResultProductInfo(result: String?) {
        // TODO parse & do something
    }

    fun handleResult___Info(result: String?) {
        // TODO parse & do something
    }

    // ... and Others

i want use coroutine for readability not callback structure. callback structure is not good method for readability i think.

so, i applied suspendCoroutine to library's listener for look like synchronous readability. but, suspendCoroutine is suspend it functions when to until call it.resume

what is best practice in this case?

    private val library : OtherLibrary = OtherLibrary()
    private val retryCount: HashMap<String?, Int> = HashMap()

    fun start(){
        CoroutineScope(Dispatchers.IO).launch{
            handleResultUserInfo(callAPI("UserInfo"))
            handleResultProductInfo(callAPI("ProductInfo"))
            handleResult___Info(callAPI("___Info"))
        }
    }

    suspend fun callAPI(apiName: String, listener:ApiListener? = null) : String? = suspendCoroutine{
        val listener = listener ?: object : ApiListener {
            override fun onSucceeded(apiName: String, result: String?) = it.resume(result)
            override fun onUpdate(apiName: String, version: String) = library.callApi(apiName, this)
            override fun onFailed(apiName: String) = retry(apiName, this)
        }
        retryCount[apiName] = 0
        library.callApi(apiName, listener)
    }

ā†‘ it waiting complete of previous work. it's not call api at same time

so i try to like this.

    fun start(){
        val callDataArr = arrayOf(
            CallData("UserInfo", ::handleResultUserInfo),
            CallData("ProductInfo", ::handleResultProductInfo),
            CallData("___Info", ::handleResult___Info),
            // ... and others
        )

        callDataArr.forEach {
            CoroutineScope(Dispatchers.IO).launch{
                it.handler(callAPI(it.apiName))
            }
        }
    }

but... it doesn't look good.

because, CoroutineScope(Dispatchers.IO).launch called a lot of times

is not good for performance or have other problems?

kotlin

asynchronous

callback

listener

coroutine

0 Answers

Your Answer

Accepted video resources