Dealing with asynchronous callbacks in Java

2k Views Asked by At

One of my OpenFeint methods to recover leaderboard data needs an asynchronous callback to a method that is supposed to modify one of my local variables (using a wonderful hack). My problem now is that once the CB is called the execution continues and, as the score value has not changed yet it returns a nullPointer. Any way to make everything synchronize or return the callback value from the main function?

private long getScoreLeaderBoard(String idLeaderBoard) {
    for (Leaderboard l : OpenFeintX.leaderboards) {
        if (l.name == null)
            break;
        if (l.resourceID().equalsIgnoreCase(idLeaderBoard)) {
            final Score s[] = new Score[1];
            l.getUserScore(OpenFeint.getCurrentUser(),
                    new Leaderboard.GetUserScoreCB() {

                        @Override
                        public void onSuccess(Score score) {
                            s[0] = score;
                        }
                    });
            if (s[0] != null) // If user has no score onSuccess get a null
                return s[0].score;
            else
                return 0;
        }
    }

    return 0;
}

Callback definition: http://m.the9.com/ioshelp/Android_en/doc/com/openfeint/api/resource/Leaderboard.GetUserScoreCB.html

3

There are 3 best solutions below

2
tyczj On

Override the onPostExecute of the AsyncTask and do what you need to do in there

3
Rob I On

If your method can stand to block while the asynchronous callback is executing, you could have it create a CountDownLatch like this:

private long getScoreLeaderBoard(String idLeaderBoard) {
    final CountDownLatch cdl = new CountDownLatch(1);
    ...
                    @Override
                    public void onSuccess(Score score) {
                        s[0] = score;
                        cdl.countDown();
                    }
    ...
        cdl.await();
        return s[0].score;
    ...
}
4
zapl On

instead of

private long getScoreLeaderBoard(String idLeaderBoard) { /* takes long */ }

make it

private void requestScoreLeaderBoardUpdate(String idLeaderBoard) { /* takes long */ }

and put the code that handled the returnvalue of getScoreLeaderBoard in (or call the method of it from) onSuccess.

That way you don't have to wait and block your thread.

You can also let your Activity implement Leaderboard.GetUserScoreCB and then it's like having another onCreate, onClick, ... like method.

class MyActivity extends Activity implements Leaderboard.GetUserScoreCB {

    private void requestScoreLeaderBoardUpdate(String idLeaderBoard) {
        // ..
        l.getUserScore(OpenFeint.getCurrentUser(), this /* your activity */);
    }

    @Override
    public void onSuccess(Score score) {
        s[0] = score;
        // do anything you want with the new score here
    }
}