简体   繁体   中英

Java guarantee callback order execution

How do I guarantee the execution of a certain code after another on Android?

I have an asynchronous callback, done, which gets executed in another thread after a Parse api query finishes, here is the code

Init() {
    ParseQuery<ParseObject> query = ParseQuery.getQuery("MyTable");
    query.getInBackground("ObjectID", new GetCallback<ParseObject>() {
        public void done(ParseObject object, ParseException e) {
             // [ ... some code ... ] <----------.
        } //                                     |
    }); //                                       |
    // I'd like this is executed after this -----'
}

So I tried this, but didn't work, it blocks when tries to acquire the second time the semaphore

private final Semaphore available = new Semaphore(1, true);
Init() {
    try {
        available.acquire();
        ParseQuery<ParseObject> query = ParseQuery.getQuery("MyTable");
        query.getInBackground("ObjectID", new GetCallback<ParseObject>() {
            public void done(ParseObject object, ParseException e) {
                // [ ... code ... ]
                available.release();
            }
        });
        available.acquire(); // waits till release
        available.release();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

Is it because semaphore is released in a thread that didn't acquire it? How to fix this solution?

However, I also tried this dummy way of solving the problem

private static volatile Boolean available = false;
Init() {
    available = false;
    ParseQuery<ParseObject> query = ParseQuery.getQuery("MyTable");
    query.getInBackground("ObjectID", new GetCallback<ParseObject>() {
        public void done(ParseObject object, ParseException e) {
            // [ ... some code ... ]
            available = true;
        }
    });
    while (available == false);
}

But it didn't work, it blocks inside the loop, and callback does not get executed. By removing the loop in this one the callback gets executed, so the problem must be related with the loop

I usually do it with CountDownLatch . As far as I could check, it exists in Android API too ( here ), so you can use it:

Init() {
    ParseQuery<ParseObject> query = ParseQuery.getQuery("MyTable");
    final taskFinishedLatch = new CountDownLatch(1);
    query.getInBackground("ObjectID", new GetCallback<ParseObject>() {
        public void done(ParseObject object, ParseException e) {
             try {
                 // [ ... some code ... ]
             } finally {
                 taskFinishedLatch.countDown();
             }
        } //                                     |
    }); //                                       |
    taskFinishedLatch.await();
    // alternatively, you can use timeouts, e.g.
    // taskFinishedLatch.await(5,  TimeUnit.SECONDS);
}

There is only one caveat here: you need to make sure that the taskFinishedLatch.countDown(); is being invoked. This is why I added the try {...} finally {...} blocks.

In this case this is not enough though. You need to handle the case when the query does not call the done callback. Ie is there an error callback? You can use time timeouts, like taskFinishedLatch.await(5, TimeUnit.SECONDS) , but that makes the behavior a bit fuzzy.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM