I didn\'t find any help on this topic. The Docs say
Cursor-based pagination is the most efficient method of paging and should always be used where possibl
I use this code:
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);
What I did in my project is basically doing the first call in onSearchClicked()
and getting result in onCompleted()
callback in ViewModel. If nextRequest
is null, I return the list of results back to my fragment, if not, I do the next call, until the end is reached (nextRequest == null
). Then, the accumulated list is returned to the fragment.
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.")
}
}
Though it's true that you should use GraphResponse.getRequestForPagedResults(), you can't use executeAndWait()
unless you run it in a different thread.
You can make it even easier using executeAsync()
.
To get the first set of results:
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();
Use that lastGraphResponse to get the next set of results:
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();
}
You can merge all that in a single method!
I figured out a good way to traverse through facebook graph api pages using cursor pagination
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);
Do not reinvent the wheel.
GraphResponse class already has a convenient method for paging. GraphResponse.getRequestForPagedResults()
returns GraphRequest
object, and you can use that object for paging.
Also I found code snippet from facebook-android-sdk's unit test code.
GraphRequest nextRequest = response.getRequestForPagedResults(GraphResponse.PagingDirection.NEXT);
nextRequest.setCallback(request.getCallback());
response = nextRequest.executeAndWait();