studio publishprogress oncancelled example create clase cancel asynctask java android ios swift android-asynctask

java - publishprogress - execute asynctask android



Android cómo agrupar tareas asincrónicas como en iOS (8)

No es necesario, pero la manera más fácil de resolver este problema es mediante el uso de la modificación con rxJava en lugar de volea.

Tengo una función en la aplicación iOS que usa dispatch_group para agrupar varias solicitudes de descanso:

static func fetchCommentsAndTheirReplies(articleId: String, failure: ((NSError)->Void)?, success: (comments: [[String: AnyObject]], replies: [[[String: AnyObject]]], userIds: Set<String>)->Void) { var retComments = [[String: AnyObject]]() var retReplies = [[[String: AnyObject]]]() var retUserIds = Set<String>() let queue = dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0) Alamofire.request(.GET, API.baseUrl + API.article.listCreateComment, parameters: [API.article.articleId: articleId]).responseJSON { response in dispatch_async(queue) { guard let comments = response.result.value as? [[String: AnyObject]] else { failure?(Helper.error()) return } print(comments) retComments = comments let group = dispatch_group_create() for (commentIndex, comment) in comments.enumerate() { guard let id = comment["_id"] as? String else {continue} let relevantUserIds = helperParseRelaventUserIdsFromEntity(comment) for userId in relevantUserIds { retUserIds.insert(userId) } retReplies.append([[String: AnyObject]]()) dispatch_group_enter(group) Alamofire.request(.GET, API.baseUrl + API.article.listCreateReply, parameters: [API.article.commentId: id]).responseJSON { response in dispatch_async(queue) { if let replies = response.result.value as? [[String: AnyObject]] { for (_, reply) in replies.enumerate() { let relevantUserIds = helperParseRelaventUserIdsFromEntity(reply) for userId in relevantUserIds { retUserIds.insert(userId) } } retReplies[commentIndex] = replies } dispatch_group_leave(group) } } } dispatch_group_wait(group, DISPATCH_TIME_FOREVER) success(comments: retComments, replies: retReplies, userIds: retUserIds) } } }

Como puede ver en mi código, busco todos los comments en el mismo article y luego obtengo replies debajo de cada comment . Después de que se hayan realizado todas las solicitudes, invoco mi success devolución de llamada. Esto se puede lograr utilizando el dispatch_group de GCD.

Ahora estoy migrando la misma funcionalidad a Android.

public static void fetchCommentsAndTheirReplies(Context context, String articleId, final StringBuffer outErrorMessage, final Runnable failure, final ArrayList<JSONObject> outComments, final ArrayList<ArrayList<JSONObject>> outReplies, final HashSet<String> outUserIds, final Runnable success) { final RequestQueue queue = Volley.newRequestQueue(context); HashMap<String, String> commentParams = new HashMap<>(); commentParams.put(API.article.articleId, articleId); JsonArrayRequest commentRequest = new JsonArrayRequest(Request.Method.GET, API.baseUrl + API.article.listCreateComment, new JSONObject(commentParams), new Response.Listener<JSONArray>() { @Override public void onResponse(JSONArray response) { try { for (int i = 0; i < response.length(); i++) { JSONObject comment = response.getJSONObject(i); outComments.add(comment); outUserIds.addAll(helperParseRelaventUserIdsFromEntity(comment)); outReplies.add(new ArrayList<JSONObject>()); //TODO: DISPATCH_GROUP? String id = comment.getString("_id"); HashMap<String, String> replyParams = new HashMap<>(); replyParams.put(API.article.commentId, id); final int finalI = i; JsonArrayRequest replyRequest = new JsonArrayRequest(Request.Method.GET, API.baseUrl + API.article.listCreateReply, new JSONObject(replyParams), new Response.Listener<JSONArray>() { @Override public void onResponse(JSONArray response) { try { for (int j = 0; j < response.length(); j++) { JSONObject reply = response.getJSONObject(j); outUserIds.addAll(helperParseRelaventUserIdsFromEntity(reply)); outReplies.get(finalI).add(reply); } } catch (JSONException ex) {} } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) {} }); queue.add(replyRequest); } success.run(); } catch (JSONException ex) {} } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { outErrorMessage.append(error.getMessage()); failure.run(); } }); queue.add(commentRequest); }

Tenga en cuenta que estoy utilizando el success se ejecuta justo después de recibir todos los comments , y antes de obtener todas las replies .

Entonces, ¿cómo puedo agruparlos y retrasar la respuesta?

Estoy trabajando en la implementación peluda como

taskCount++; if (taskCount == totalCount) { success.run(); }

en bloque de respuesta, pero parece muy tedioso.


No hay un análogo directo de dispatch_group en Java o Android. Puedo recomendar algunas técnicas bastante sofisticadas para producir una solución realmente limpia y elegante si estás listo para invertir algo de tiempo extra en ella. No va a haber una o dos líneas de código, desafortunadamente.

  1. Use RxJava con paralelización . RxJava proporciona una forma limpia de despachar múltiples tareas, pero funciona de forma secuencial por defecto. Consulte este artículo para hacer que ejecute tareas al mismo tiempo.

  2. Aunque este no es exactamente el caso de uso previsto, puede probar ForkJoinPool para ejecutar su grupo de tareas y luego recibir un resultado único.


No use Java

Dale una oportunidad a Kotlin, tiene promesas

task { //some (long running) operation, or just: 1 + 1 } then { i -> "result: $i" } success { msg -> println(msg) }

https://github.com/mplatvoet/kovenant


Pruebe Priority Job Queue: https://github.com/yigit/android-priority-jobqueue

Priority Job Queue es una implementación de Job Queue específicamente escrita para Android para programar fácilmente trabajos (tareas) que se ejecutan en segundo plano, mejorando el UX y la estabilidad de las aplicaciones.

(...)

Puede agrupar trabajos para garantizar su ejecución en serie, si es necesario. Por ejemplo, supongamos que tiene un cliente de mensajería y su usuario envió varios mensajes cuando su teléfono no tenía cobertura de red. Al crear estos trabajos de SendMessageToNetwork, puede agruparlos por ID de conversación. A través de este enfoque, los mensajes en la misma conversación se enviarán en el orden en que fueron en cola, mientras que los mensajes entre diferentes conversaciones se siguen enviando en paralelo. Esto le permite maximizar sin esfuerzo la utilización de la red y garantizar la integridad de los datos.


Puede usar Thread s y Thread.join() con Handler s como una opción.

cita de: https://docs.oracle.com/javase/tutorial/essential/concurrency/join.html

El método de unión permite que un subproceso espere la finalización de otro. Si t es un objeto Thread cuyo hilo se está ejecutando actualmente,

t.join (); hace que el hilo actual pause la ejecución hasta que termina el hilo de t. Las sobrecargas de unión permiten al programador especificar un período de espera. Sin embargo, al igual que con la suspensión, la unión depende del sistema operativo para el tiempo, por lo que no debe suponer que la unión esperará exactamente el tiempo que especifique.

Como sleep, join responde a una interrupción al salir con una InterruptedException.

EDITAR : También debe verificar mi esencia de despachador de eventos . Te puede gustar


Simplemente puede hacerlo con esta clase que hice para imitar el comportamiento de iOS. Llame a enter () y leave () de la misma manera que lo hizo en iOS con dispatch_group_enter y dispatch_group_leave y llame a notify () justo después de las solicitudes que desea agrupar, al igual que dispatch_group_notify. También usa el ejecutable de la misma manera en que iOS usa bloques:

public class DispatchGroup { private int count = 0; private Runnable runnable; public DispatchGroup() { super(); count = 0; } public synchronized void enter(){ count++; } public synchronized void leave(){ count--; notifyGroup(); } public void notify(Runnable r) { runnable = r; notifyGroup(); } private void notifyGroup(){ if (count <=0 && runnable!=null) { runnable.run(); } } }

Espero eso ayude ;)


Su implementación "peluda" no es "peluda" en absoluto.

public void onResponse(JSONArray response) { try { final int[] taskFinished = {0}; final int taskTotal = response.length(); for (int i = 0; i < response.length(); i++) { JSONObject comment = response.getJSONObject(i); outComments.add(comment); outUserIds.addAll(helperParseRelaventUserIdsFromEntity(comment)); outReplies.add(new ArrayList<JSONObject>()); //TODO: DISPATCH_GROUP? String id = comment.getString("_id"); HashMap<String, String> replyParams = new HashMap<>(); replyParams.put(API.article.commentId, id); final int finalI = i; JsonArrayRequest replyRequest = new JsonArrayRequest(Request.Method.GET, API.baseUrl + API.article.listCreateReply, new JSONObject(replyParams), new Response.Listener<JSONArray>() { @Override public void onResponse(JSONArray response) { taskFinished[0]++; try { for (int j = 0; j < response.length(); j++) { JSONObject reply = response.getJSONObject(j); outUserIds.addAll(helperParseRelaventUserIdsFromEntity(reply)); outReplies.get(finalI).add(reply); } } catch (JSONException ex) {} if (taskFinished[0] == taskTotal) { success.run(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { taskFinished[0]++; if (taskFinished[0] == taskTotal) { success.run(); } } }); queue.add(replyRequest); } } catch (JSONException ex) {} }