OMG*_*POP 27 java android ios android-asynctask swift
我在iOS应用程序中有一个功能,用于dispatch_group对多个休息请求进行分组:
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)
}
}
}
Run Code Online (Sandbox Code Playgroud)
正如你从我的代码中看到的那样,我获取所有comments相同的内容article,然后replies在每个下面获取相应的内容comment.完成所有请求后,我调用我的success回调.这可以使用GCD实现dispatch_group.
现在我将相同的功能迁移到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);
}
Run Code Online (Sandbox Code Playgroud)
请注意,我使用的success是在我获得所有内容之后立即执行comments,并且在获得所有内容之前执行replies.
那么如何对它们进行分组并延迟响应呢?
我正在研究毛茸茸的实现
taskCount++;
if (taskCount == totalCount) {
success.run();
}
Run Code Online (Sandbox Code Playgroud)
在回复块,但似乎非常繁琐.
Dam*_*aca 21
您可以使用我为模仿iOS行为而创建的这个类来完成它.调用enter()和leave(),就像你在iOS中使用dispatch_group_enter和dispatch_group_leave一样,并在你想要分组的请求之后调用notify(),就像dispatch_group_notify一样.它也像iOS使用块一样使用runnable:
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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
希望能帮助到你 ;)
这是Damien Praca的答案的Kotlin版本。这样您就可以像这样使用Kotlin lambda。
val dispatchGroup = DispatchGroup()
dispatchGroup.enter()
// Some long running task
dispatchGroup.leave()
dispatchGroup.notify {
// Some code to run after all dispatch groups complete
}
class DispatchGroup {
private var count = 0
private var runnable: (() -> Unit)? = null
init {
count = 0
}
@Synchronized
fun enter() {
count++
}
@Synchronized
fun leave() {
count--
notifyGroup()
}
fun notify(r: () -> Unit) {
runnable = r
notifyGroup()
}
private fun notifyGroup() {
if (count <= 0 && runnable != null) {
runnable!!()
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以使用Threads 和Thread.join()with Handlers 作为选项。
引用自: https: //docs.oracle.com/javase/tutorial/essential/concurrency/join.html
join 方法允许一个线程等待另一个线程的完成。如果 t 是一个 Thread 对象,其线程当前正在执行,
t.join(); 导致当前线程暂停执行,直到 t 的线程终止。join 的重载允许程序员指定等待时间。但是,与 sleep 一样,join 依赖于操作系统的计时,因此您不应假设 join 将完全等待您指定的时间。
与 sleep 一样,join 通过退出并抛出 InterruptedException 来响应中断。
编辑:您还应该检查我的事件调度程序要点。你可能会喜欢它。
| 归档时间: |
|
| 查看次数: |
3761 次 |
| 最近记录: |