Facebook API how to wait til graphRequest executeA

2020-06-30 04:13发布

问题:

I am using facebook graph request to retrieve friends list. But, How can I get to create a function and return it after the call graphRequest.executeAsync() is done?.

private Map<String, String> getFacebookFriends(AccessToken accessToken, Profile profile) throws InterruptedException, ExecutionException {
    final Map<String, String> friendsMap = new HashMap<>();
    GraphRequest graphRequest = new GraphRequest(accessToken, "/me/friends", null, HttpMethod.GET,
            new GraphRequest.Callback() {
                public void onCompleted(GraphResponse response) {
                    JSONObject jGraphObj = response.getJSONObject();
                    try {
                        JSONArray friendsData = jGraphObj.getJSONArray("data");
                        for (int i = 0; i < friendsData.length(); i++) {
                            JSONObject friend = friendsData.getJSONObject(i);
                            String friendId = friend.getString("id");
                            String friendName = friend.getString("name");
                            friendsMap.put(friendId, friendName);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
    );
    List<GraphResponse> gResponseList = graphRequest.executeAsync().get();
    return friendsMap;
}

I am currently using the same technique like in this post. By calling it like graphRequest.executeAsync().get();. But it seems like it's not working.

The function above will return the friendsMap before the graphRequest is done.

Any suggestion is appreciated.

回答1:

I've got this working by using executeAndWait instead of executeAsync function. So, this is how the final looks like

public static Map<String, String> getFacebookFriends(AccessToken accessToken, Profile profile) throws InterruptedException, ExecutionException {
    final Map<String, String> friendsMap = new HashMap<>();

    GraphRequest.Callback gCallback = new GraphRequest.Callback() {
        public void onCompleted(GraphResponse response) {
            JSONObject jGraphObj = response.getJSONObject();
            try {
                JSONArray friendsData = jGraphObj.getJSONArray("data");
                for (int i = 0; i < friendsData.length(); i++) {
                    JSONObject friend = friendsData.getJSONObject(i);
                    String friendId = friend.getString("id");
                    String friendName = friend.getString("name");
                    friendsMap.put(friendId, friendName);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };
    final GraphRequest graphRequest = new GraphRequest(accessToken, "/me/friends", null, HttpMethod.GET, gCallback);
    // Run facebook graphRequest.
    Thread t = new Thread(new Runnable() {
        @Override
        public void run() {
            GraphResponse gResponse = graphRequest.executeAndWait();
        }
    });
    t.start();
    t.join();
    return friendsMap;
}


回答2:

For anyone who needs the version in C#. This is what I have in my Main activity.

    public static ICallbackManager CallbackManager = CallbackManagerFactory.Create();
    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);

        var facebookCallback = new FacebookCallback<LoginResult>
        {
            HandleSuccess = async shareResult =>
            {
                Bundle parameters = new Bundle();
                parameters.PutString("fields", "id,name,link,email,picture.type(normal),friends");

                GraphRequest request = new GraphRequest(
                    shareResult.AccessToken,
                    "/me",
                    parameters, HttpMethod.Get, new OnGraphResulCallback());

                await Task.Run(() =>
                {
                    var fbResponse = JsonConvert.DeserializeObject<FbResponse>(request.ExecuteAndWait().RawResponse);
                });
            },
            HandleCancel = () =>
            {
                Console.WriteLine("HelloFacebook: Canceled");
            },
            HandleError = shareError =>
            {
                Console.WriteLine("HelloFacebook: Error: {0}", shareError);
            }
        };

        // fb init 
        FacebookSdk.SdkInitialize(this.ApplicationContext);
        LoginManager.Instance.RegisterCallback(MainActivity.CallbackManager, facebookCallback);

        Forms.Init(this, bundle);
        LoadApplication(App.Instance);
    }

and here are the helper classes:

public class FacebookCallback<TResult> : Java.Lang.Object, IFacebookCallback where TResult : Java.Lang.Object
{
    public Action HandleCancel { get; set; }
    public Action<FacebookException> HandleError { get; set; }
    public Action<TResult> HandleSuccess { get; set; }

    public void OnCancel()
    {
        HandleCancel.Invoke();
    }

    public void OnError(FacebookException error)
    {
        HandleError.Invoke(error);            
    }

    public void OnSuccess(Java.Lang.Object result)
    {
        HandleSuccess.Invoke(result.JavaCast<TResult>());
    }
}

public class FbResponse
{
    public long Id { get; set; }
    public string Name { get; set; }
    public Picture Picture { get; set; }
    public Friends Friends { get; set; }
    public string Email { get; set; }
}
public class Friends
{
    public List<FriendsData> Data { get; set; }
    public Paging Paging { get; set; }
    public Summary Summary { get; set; }
}
public class Summary
{
    public int Total_Count { get; set; }
}
public class Paging
{
    public Cursors Cursors { get; set; }
}
public class Cursors
{
    public string Before { get; set; }
    public string After { get; set; }
}
public class FriendsData
{
    public int Id { get; set; }
    public string Name { get; set; }
}
public class Picture
{
    public PictureData Data { get; set; }
}
public class PictureData
{
    public bool Is_Silhouette { get; set; }
    public string Url { get; set; }
}