Правильно ли запускать сопрограммы Kotlin из java-файла активности?

Android Studio 3.4

classpath 'com.android.tools.build:gradle:3.4.2'

в файле Kotlin: TransportService.kt

import kotlinx.coroutines.*
import retrofit2.Response


  @JvmStatic
        fun doLoginFromJava(
            email: String,
            password: String,
            isCustomtHandle: Boolean = false
        ): CompletableFuture<Response<*>> = GlobalScope.future {
            login(email, password, isCustomtHandle)
        }


suspend fun login(email: String, password: String, isCustomtHandle: Boolean = false): Response<*> {
            val json = JsonObject()
            json.addProperty("email", email);
            json.addProperty("password", password);
            suspend fun execOperation(): Response<*> = myRestClient.login(json)
            return runOperation(isCustomtHandle, ::execOperation)
}

Ее интерфейс api:

import com.google.gson.JsonElement
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.POST

/*
  Notice we are calling the suspend method in order to wait until our asynchronous operation has finished.
  Awaits for completion of this value without blocking a thread and resumes when deferred computation is complete,
  returning the resulting value (e.g. after 3 seconds) or throwing the corresponding exception if the deferred was cancelled.
*/
interface TangoRestClient {

    @POST("/login")
    suspend fun login(@Body body: JsonElement) : Response<JsonElement>  


}

используйте это из файла активности Kotlin (TradersActivity.kt):

import android.app.Activity;
class TradersActivity :Activity

    private fun loadData() {
        GlobalScope.launch(Dispatchers.Main) {
            val response: Response<*> = TransportService.login("email", "password")
             if (response.get().isSuccessful()) {
                     Toast.makeText(context, "Success response", Toast.LENGTH_SHORT).show();
                }
        }
    }

Хорошо, что все работает нормально.

OK.

Но у меня также есть файл java, который должен использовать ту же логику. И который я пока не могу преобразовать в Kotlin.

Мне нужно запустить сопрограмму Kotlin из java и запустить метод doLoginFromJava в потоке IO (асинхронный). Также результат должен отображаться в потоке UI, чтобы отображался тост.

Поэтому я пробую это в java-файле LoginActivity.java (я вызываю метод doLoginFromJava)

 import android.app.Activity;
public class LoginActivity extends Activity {

  try {
        CompletableFuture<Response<?>> response = TransportService.doLogin("email", "pass", false);
        if (BuildConfig.DEBUG)
            Log.d(TAG, "login_response = " + response);
        if (response.get().isSuccessful()) {
            Toast.makeText(getApplicationContext(), "Success reponse", Toast.LENGTH_SHORT).show();
        }
    } catch (ExecutionException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

Вопрос в том, является ли это правильным эквивалентом кода Kotlin?


person Alex    schedule 15.07.2019    source источник


Ответы (1)


Нет, это не эквивалентно, поскольку response.get() заблокирует поток пользовательского интерфейса.

Вы просто не сможете воспроизвести функциональность сопрограмм как одного метода, поскольку они предназначены для работы с «прерываниями» в выполнении, во время которых может выполняться другой код. Вам нужно будет реализовать обычное Handler решение и решение на основе обратного вызова для работы с данными, которые будут доступны в какой-то момент в будущем.

Однако вы можете подумать о реализации части, требующей сопрограмм, в kotlin, а затем просто вызвать ее из LoginActivity, по существу медленно перемещая реализацию по мере необходимости.

person Kiskae    schedule 15.07.2019