0

I am using the Facebook graph api to find out what pages a user is apart of. When the query comes back with a json object it has what I need but, for some reason it doesn't want to add to my array list. The correct value is printed in log.d it seems to skip my arraylist for some reason. Any ideas?

Find page function

private ArrayList<String> foundPages;
private JSONObject jsonObject; 

public ArrayList<String> findPages()
{
    accessToken = AccessToken.getCurrentAccessToken();
    foundPages = new ArrayList<>();

    GraphRequest request = GraphRequest.newGraphPathRequest(
            accessToken,
            "/me/accounts",
            new GraphRequest.Callback() {
                @Override
                public void onCompleted(GraphResponse response) {

                    try {

                        jsonObject = response.getJSONObject();
                        for(int i=0; i < jsonObject.getJSONArray("data").length(); i++)
                        {
                         page = response.getJSONObject().getJSONArray("data").getJSONObject(i).getString("name");
                            Log.d("viewmodel",page);
                            foundPages.add(page);

                        }

                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            });

    request.executeAsync();


    return foundPages;
} 
2
  • @GhostCat is actually right. You are returning a list before it is give any value. You can add to your post the block where called findPages() for futher assistance. Commented Jul 31, 2019 at 19:47
  • i made this as an easy reference for these types of problems in future stackoverflow.com/questions/57330766/… Commented Aug 2, 2019 at 17:34

2 Answers 2

2

There is a common way to solve this problem, which is to define a callback method which will return these values to you, AFTER they have been populated by the call, which goes something like this (my java is rusty, bear with me...)

define an interface :

 interface Callback{
        void apiResponseCallback(ArrayList<Page> result);//whatever your model is, make the array of that type
    }

then, in your normal findPages method, change it to this:

public void findPages(Callback callback) {
    //
    // 
    ........
     for(int i=0; i < jsonObject.getJSONArray("data").length(); i++)
                    {
                     page = response.getJSONObject().getJSONArray("data").getJSONObject(i).getString("name");
                        Log.d("viewmodel",page);
                        foundPages.add(page);

                    } 
    callback.apiResponseCallback(foundPages);//here we are returning the data when it is done
}

then, when you call findPages

findPages(new Callback() {
        @Override
        public void apiResponseCallback(ArrayList<Page> result) {
            here, this result parameter that comes through is your api call result to use, so result will be your populated pages to use.
        }
    });
}

sake of completeness:

public void findPages(Callback callback)
{
    accessToken = AccessToken.getCurrentAccessToken();
    foundPages = new ArrayList<>();

    GraphRequest request = GraphRequest.newGraphPathRequest(
            accessToken,
            "/me/accounts",
            new GraphRequest.Callback() {
                @Override
                public void onCompleted(GraphResponse response) {

                    try {

                        jsonObject = response.getJSONObject();
                        for(int i=0; i < jsonObject.getJSONArray("data").length(); i++)
                        {
                         page = response.getJSONObject().getJSONArray("data").getJSONObject(i).getString("name");
                            Log.d("viewmodel",page);
                            foundPages.add(page);

                        }
                        callback.apiResponseCallback(foundPages);

                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            });

    request.executeAsync();
} 
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you a_local_nobody Its a nice answer.
1

Yep. This here:

request.executeAsync();

triggers an asynchronous request. But your "current" thread simply continues to do:

return foundPages;

and it returns an empty list.

That list gets later filled, but at the moment in time when that method returns, that list is still empty. Or just gets filled. Who knows, as it gets filled asynchronously, at some unknown point in the future.

A solution could be to have some other variable/field that tells you the data has arrived and pushed into the list.

Alternatively, that method could just make a synchronous request, simply block the caller from progressing until the data has arrived.

You see, you can't have it both ways: when you don't wait for your results to arrive, you shouldn't expect them to be available immediately.

1 Comment

stackoverflow.com/questions/57330766/… I made this as a reference for these types of questions in future, hopefully it doesn't exist already

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.