如何使用Facebook Graph Api基于光标的分页

时间:2015-04-27 17:30:17

标签: android facebook-graph-api pagination

我在这个主题上找不到任何帮助。文件说

  

基于游标的分页是最有效的分页方法,应尽可能使用 - 游标是指随机字符串,用于标记数据列表中的特定项目。除非删除此项,否则光标将始终指向列表的相同部分,但如果删除项,则无效。因此,您的应用不应存储任何旧游标或假设它们仍然有效。

When reading an edge that supports cursor pagination, you will see the following JSON response:

{
  "data": [
     ... Endpoint data is here
  ],
  "paging": {
    "cursors": {
      "after": "MTAxNTExOTQ1MjAwNzI5NDE=",
      "before": "NDMyNzQyODI3OTQw"
    },
    "previous": "https://graph.facebook.com/me/albums?limit=25&before=NDMyNzQyODI3OTQw"
    "next": "https://graph.facebook.com/me/albums?limit=25&after=MTAxNTExOTQ1MjAwNzI5NDE="
  }
}

我使用这种格式进行api调用,如何遍历循环中的所有页面

/* make the API call */
new GraphRequest(
    session,
    "/{user-id}/statuses",
    null,
    HttpMethod.GET,
    new GraphRequest.Callback() {
        public void onCompleted(GraphResponse response) {
            /* handle the result */
        }
    }
).executeAsync();

5 个答案:

答案 0 :(得分:12)

我想出了一个使用光标分页遍历facebook图表api页面的好方法

    final String[] afterString = {""};  // will contain the next page cursor
    final Boolean[] noData = {false};   // stop when there is no after cursor 
    do {
        Bundle params = new Bundle();
        params.putString("after", afterString[0]);
        new GraphRequest(
                accessToken,
                personId + "/likes",
                params,
                HttpMethod.GET,
                new GraphRequest.Callback() {
                    @Override
                    public void onCompleted(GraphResponse graphResponse) {
                        JSONObject jsonObject = graphResponse.getJSONObject(); 
                        try {
                            JSONArray jsonArray = jsonObject.getJSONArray("data");

                            //  your code 


                            if(!jsonObject.isNull("paging")) {
                                JSONObject paging = jsonObject.getJSONObject("paging");
                                JSONObject cursors = paging.getJSONObject("cursors");
                                if (!cursors.isNull("after"))
                                    afterString[0] = cursors.getString("after");
                                else
                                    noData[0] = true;
                            }
                            else
                                noData[0] = true;
                        } catch (JSONException e) {
                            e.printStackTrace(); 
                        }
                    }
                }
        ).executeAndWait();
    }
    while(!noData[0] == true);

答案 1 :(得分:10)

不要重新发明轮子。

GraphResponse类已经有了一种方便的分页方法。 GraphResponse.getRequestForPagedResults()返回 GraphRequest个对象,您可以使用该对象进行分页。

我还找到了来自facebook-android-sdk's unit test code的代码段。

GraphRequest nextRequest = response.getRequestForPagedResults(GraphResponse.PagingDirection.NEXT);
nextRequest.setCallback(request.getCallback());
response = nextRequest.executeAndWait();

答案 2 :(得分:5)

虽然您应该使用GraphResponse.getRequestForPagedResults(),但除非您在其他主题中运行,否则无法使用executeAndWait()

使用executeAsync()可以更轻松。

获取第一组结果

    new GraphRequest(AccessToken.getCurrentAccessToken(),
            "/" + facebookID + "/invitable_friends",
            null,
            HttpMethod.GET,
            new GraphRequest.Callback() {
                public void onCompleted(GraphResponse response) {
                    //your code

                    //save the last GraphResponse you received
                    lastGraphResponse = response;
                }
            }
    ).executeAsync();

使用lastGraphResponse 获取下一组结果

    GraphRequest nextResultsRequests = lastGraphResponse.getRequestForPagedResults(GraphResponse.PagingDirection.NEXT);
    if (nextResultsRequests != null) {
        nextResultsRequests.setCallback(new GraphRequest.Callback() {
            @Override
            public void onCompleted(GraphResponse response) {
                //your code

                //save the last GraphResponse you received
                lastGraphResponse = response;
            }
        });
        nextResultsRequests.executeAsync();
    }

您可以在一个方法中合并所有内容!

答案 3 :(得分:3)

我使用此代码:

final String[] afterString = {""}; 
final Boolean[] noData = {true};
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);

do{
   GraphRequest request = GraphRequest.newGraphPathRequest(
            AccessToken.getCurrentAccessToken(),
            "/me/likes",
            new GraphRequest.Callback() {
                @Override
                public void onCompleted(GraphResponse response) {
                    // Insert your code here
                    JSONObject jsonObject = response.getJSONObject();
                    try{
                        if(jsonObject.length() > 1) {

                            JSONObject jsonFacebook = (JSONObject) new JSONTokener(jsonObject.toString()).nextValue();
                            JSONObject likes_paging = (JSONObject) new JSONTokener(jsonFacebook.getJSONObject("paging").toString()).nextValue();

                            ArrayList<String> likes = new ArrayList<String>();
                            for (int i = 0; i < jsonFacebook.getJSONArray("data").length(); i++) {
                                likes.add(jsonFacebook.getJSONArray("data").getJSONObject(i).getString("name"));
                            }
                            afterString[0] = (String) likes_paging.getJSONObject("cursors").get("after");

                        }else{
                            noData[0] = false;
                        }
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            });

    Bundle parameters = new Bundle();
    parameters.putString("pretty", "0");
    parameters.putString("limit", "100");
    parameters.putString("after", afterString[0]);
    request.setParameters(parameters);
    request.executeAndWait();
}while(noData[0] == true);

答案 4 :(得分:0)

我在项目中所做的基本上是在onSearchClicked()中进行首次调用,并在ViewModel的onCompleted()回调中获得结果。如果nextRequest为空,我将结果列表返回到片段,否则返回下一个调用,直到到达末尾(nextRequest == null)。然后,将累积的列表返回到片段。

class SearchViewModel() : GraphRequest.Callback {

    private var allPlaces = arrayListOf<FacebookPlace>()

    fun onSearchClicked(location: Location) {
      val request = GraphRequest.newGraphPathRequest(accessToken, "/search", this)
      request.parameters = parameters
      request.executeAsync()
    }

    override fun onCompleted(response: GraphResponse?) {
      if (response != null) {
        allPlaces.addAll(response.data)

        val nextRequest = response.getRequestForPagedResults(GraphResponse.PagingDirection.NEXT)
        if (nextRequest == null) {
            uiEvent.value = ShowPlaces(allPlaces)
        } else {
            nextRequest.callback = this
            nextRequest.executeAsync()
        }
    } else {
        Log.e(TAG, "Search response is null.")
    }
}