Estoy trabajando en una aplicación de Android basada en Java. Quiero comenzar a usar Kotlin y corrutinas para el trabajo relacionado con la red fuera del hilo principal, pero me encontré con un problema al tratar de descubrir cómo manejar con éxito una situación determinada.
Creé un archivo Kotlin con una función de red que planeo llamar en una clase Java (un modelo de vista, que en este momento debe permanecer escrito en Java). La idea es que quiero que la función de red modifique y devuelva una lista al modelo de vista, y luego permita que el modelo de vista continúe.
fun performNetworking( data: MutableList<Data> ): MutableList<Data> { CoroutineScope(Dispatchers.IO).launch { data.forEach { // modify each element in the list } } return data }Actualmente, lo llamo desde el modelo de vista de Java como tal:
public void modifyData(List<Data> data) { List<Data> modifiedData = NetworkingKt.performNetworking(data); performMoreThings(modifiedData); } Con esta implementación, performMoreThings() desencadena como si ninguno de los datos de la lista se hubiera modificado. A través de la depuración, descubrí que antes de que el alcance de la rutina pueda hacer algo, se llega a la conclusión de performMoreThings() con la lista de datos sin modificar.
Por lo tanto, me pregunto si hay alguna manera de hacer que el código espere a que se complete el trabajo del alcance de la corrutina antes de devolver la lista de datos al modelo de vista de Java (sin bloquear el subproceso principal y evitar que el usuario interactúe con la aplicación)? ¿O estoy malinterpretando las habilidades, los propósitos y las implementaciones de las corrutinas y esto no es posible? ¿Tendría que pasar una referencia al modelo de vista y hacer que llame a un método de continuación una vez que se complete la rutina, como lo haría con AsyncTask en su onPostExecute() ?
No, esto no es posible. No por las limitaciones de las rutinas, sino todo lo contrario, debido a las limitaciones del código que no es de rutina. Su modifyData() es un método regular, no suspendible, por lo que de todos modos no puede esperar sin bloquear el hilo. Las funciones de suspensión de Kotlin pueden hacer esto, pero los métodos de Java no.
Debe invocar modifyData() desde el subproceso en segundo plano, por lo que el bloqueo no será un problema o rediseñar performNetworking() para usar una de las técnicas clásicas para manejar tareas asincrónicas, es decir, recibir una devolución de llamada o devolver un futuro:
fun performNetworking( data: MutableList<Data> ): CompletableFuture<MutableList<Data>> { return CoroutineScope(Dispatchers.IO).future { data.forEach { // modify each element in the list } data } } public void modifyData(List<Data> data) { NetworkingKt.performNetworking(data) .thenAccept(this::performMoreThings); }