如何使用 Facebook Graph Api 基于光标的分页
How to use the Facebook Graph Api Cursor-based Pagination
我没有找到关于此主题的任何帮助。文档说
Cursor-based pagination is the most efficient method of paging and should always be used where possible - a cursor refers to a random string of characters which mark a specific item in a list of data. Unless this item is deleted, the cursor will always point to the same part of the list, but it will be invalidated if an item is removed. Therefore, your app shouldn't store any older cursors or assume that they will still be valid.
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();
我找到了一种使用光标分页遍历 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);
我使用这个代码:
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);
不要重新发明轮子。
GraphResponse class已经有了方便的分页方法。 GraphResponse.getRequestForPagedResults()
returns GraphRequest
对象,您可以使用该对象进行分页。
我还从 facebook-android-sdk's unit test code 中找到了代码片段。
GraphRequest nextRequest = response.getRequestForPagedResults(GraphResponse.PagingDirection.NEXT);
nextRequest.setCallback(request.getCallback());
response = nextRequest.executeAndWait();
虽然您确实应该使用 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();
}
您可以将所有这些合并到一个方法中!
我在我的项目中所做的基本上是在 onSearchClicked()
中进行第一次调用并在 ViewModel 中的 onCompleted()
回调中获得结果。如果 nextRequest
为 null,我 return 将结果列表返回到我的片段,如果不是,我进行下一次调用,直到到达末尾 (nextRequest == null
)。然后,累积列表被 returned 到片段。
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.")
}
}
我没有找到关于此主题的任何帮助。文档说
Cursor-based pagination is the most efficient method of paging and should always be used where possible - a cursor refers to a random string of characters which mark a specific item in a list of data. Unless this item is deleted, the cursor will always point to the same part of the list, but it will be invalidated if an item is removed. Therefore, your app shouldn't store any older cursors or assume that they will still be valid.
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();
我找到了一种使用光标分页遍历 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);
我使用这个代码:
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);
不要重新发明轮子。
GraphResponse class已经有了方便的分页方法。 GraphResponse.getRequestForPagedResults()
returns GraphRequest
对象,您可以使用该对象进行分页。
我还从 facebook-android-sdk's unit test code 中找到了代码片段。
GraphRequest nextRequest = response.getRequestForPagedResults(GraphResponse.PagingDirection.NEXT);
nextRequest.setCallback(request.getCallback());
response = nextRequest.executeAndWait();
虽然您确实应该使用 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();
}
您可以将所有这些合并到一个方法中!
我在我的项目中所做的基本上是在 onSearchClicked()
中进行第一次调用并在 ViewModel 中的 onCompleted()
回调中获得结果。如果 nextRequest
为 null,我 return 将结果列表返回到我的片段,如果不是,我进行下一次调用,直到到达末尾 (nextRequest == null
)。然后,累积列表被 returned 到片段。
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.")
}
}