Как использовать графику Facebook Api Cursor-based 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();

Ответ 1

Я понял хороший способ пересечь страницы api facebook graph с использованием разбивки на страницы курсора

    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);

Ответ 2

Не изобретайте велосипед.

GraphResponse у класса уже есть удобный метод для подкачки. GraphResponse.getRequestForPagedResults() возвращает объект GraphRequest, и вы можете использовать этот объект для подкачки.

Также я нашел фрагмент кода из код facebook-android-sdk unit test.

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

Ответ 3

Хотя верно, что вы должны использовать 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();
    }

Вы можете объединить все это одним способом!

Ответ 4

Я использую этот код:

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);