Kotlin - запуск ksoap2 в качестве сопрограммы против asyn c - что лучше? - PullRequest
1 голос
/ 13 января 2020

Android и Kotlin noob здесь - у меня есть приложение, вызывающее веб-службу SOAP. Прямо сейчас звонки осуществляются с помощью Thread и связь работает. Я хотел бы перенести это в Kotlin сопрограмм или Android Asyn c задач, мой вопрос - что лучше в этом случае?

Я пытался создать вызов сопрограммы на основе этого article https://proandroiddev.com/how-to-make-sense-of-kotlin-coroutines-b666c7151b93, в основном адаптируя этот шаблон:

fun main() = runBlocking {
    val deferredResult = async {
        delay(1000L)
        "World!"
    }
    println("Hello, ${deferredResult.await()}")
}

Когда я помещаю вызов веб-службы в сопрограмму asyn c, тогда Android Studio выделяет метод вызова HttpTransportSE (http://www.kobjects.org/ksoap2/doc/api/org/ksoap2/transport/HttpTransportSE.html) со следующим предупреждением:

Неправильный вызов метода блокировки. Сообщает о вызовах методов блокировки потоков, найденных во фрагменте кода, где поток не должен блокироваться "

Мое понимание этого сообщения состоит в том, что вызов, сделанный HttpTransportSE, блокирует поток, поэтому мы теряем преимущество использования сопрограмм, и я должен просто придерживаться задачи Asyn c. Это правильная интерпретация, или есть способ обернуть вызов с сопрограммой, который будет работать более правильно?

Ниже мой код ( он связывается с веб-службами, но из-за предупреждения у меня возникает ощущение, что это неправильный способ сделать это):

fun callWebService(
...
): String {
    val defferedResult: Deferred<String> = GlobalScope.async {
        try {
...
            val envelope = SoapSerializationEnvelope(SoapEnvelope.VER12)
...
            val androidHttpTransport = HttpTransportSE(URL)
            androidHttpTransport.debug = true
            androidHttpTransport.call("$NAMESPACE/$methodName", envelope)    //this is where I get the warning
            val resultData = envelope.response
            webResponse = "$resultData"
...
        }
        return@async webResponse
    }
    return runBlocking { defferedResult.await() }
}

1 Ответ

0 голосов
/ 30 января 2020

Я думаю, я понял это, благодаря этой статье
все сводится к фоновому запуску с использованием Dispatchers.IO
вызов SOAP может быть обычной функцией, нет нужно для Deffered, et c.

Я использую модель MVVM с репозиторием, поэтому вся фоновая работа происходит на уровне Repository, вызванном нажатием кнопки в Fragment, запущенном в соответствующем ViewModel, с ограниченной областью

мой SOAP вызов теперь выглядит следующим образом

fun callWebService(...): String {
        try {
...
            val envelope = SoapSerializationEnvelope(SoapEnvelope.VER12)
...
            val androidHttpTransport = HttpTransportSE(URL)
            androidHttpTransport.debug = true
            androidHttpTransport.call("$NAMESPACE/$methodName", envelope)    
            val resultData = envelope.response
            webResponse = "$resultData"
...
        }
        return webResponse
}

в Repository У меня есть следующая функция - обратите внимание на suspend и Dispatchers.IO

    suspend fun insertAndSend(task: Task) {
        withContext(Dispatchers.IO) {
            val response = callWebService(processedTask)
            processedTask.status = response
            taskDao.update(processedTask)
        }
    }

в ViewModel я вызываю функцию Repository в ViewModelScope

//defined in ViewModel class
 fun insertAndSend(task: Task) = viewModelScope.launch { repository.insertAndSend(task) }

, которая вызывается в соответствующем Fragment нажатием кнопки

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...