首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >安卓如何像iOS一样将异步任务分组在一起

安卓如何像iOS一样将异步任务分组在一起
EN

Stack Overflow用户
提问于 2016-01-19 16:16:00
回答 3查看 6.5K关注 0票数 30

我在iOS应用程序中有一个使用dispatch_group对多个rest请求进行分组的函数:

代码语言:javascript
复制
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)

        }

    }
}

正如您从我的代码中看到的,我获取同一个article下的所有comments,然后获取每个comment下的对应replies。在所有请求完成后,我调用success回调函数。这可以使用GCD的dispatch_group来实现。

现在我正在将相同的功能迁移到android上。

代码语言:javascript
复制
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);
}

请注意,我使用的success是在获取所有comments之后,在获取所有replies之前立即执行的。

那么我如何对它们进行分组并延迟响应呢?

我正在做类似这样的复杂实现。

代码语言:javascript
复制
taskCount++;
if (taskCount == totalCount) {
    success.run();
} 

在回复块中,但它似乎非常繁琐。

EN

回答 3

Stack Overflow用户

发布于 2016-05-17 16:29:11

您可以简单地使用我创建的这个类来模拟iOS行为。像在iOS中对dispatch_group_enter和dispatch_group_leave调用enter()和leave()一样,在要分组的请求之后立即调用notify(),就像dispatch_group_notify一样。它使用runnable的方式与iOS使用块的方式相同:

代码语言:javascript
复制
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();
        }
    }
}

希望它能有所帮助;)

票数 30
EN

Stack Overflow用户

发布于 2018-03-24 06:27:41

以下是Damien Praca的答案的Kotlin版本。这将允许您像这样使用Kotlin lambdas。

代码语言:javascript
复制
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!!()
        }
    }
}
票数 16
EN

Stack Overflow用户

发布于 2016-01-19 16:22:14

你的“多毛”实现根本不是“多毛”的。

代码语言:javascript
复制
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) {}
            }
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34871580

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档