改造 - 如何在异步请求中发出同步请求
Retrofit - how do I make a synchronous request within an asynchronous request
我正在实施一个两级嵌套 recyclerView
,并且两个回收器视图都使用 retrofit
进行 API 调用。这是发出同步请求的方法:
public void loadSectionStories(String sessionKey, CuratedSection section) {
Call<JsonArray> subCall;
subCall = TravelersApi.endpoint().getCuratedSectionTopics(sessionKey, section.id);
try {
Response<JsonArray> response = subCall.execute();
if(response.code() != 200) {
Toast.makeText(getApplicationContext(), "Cannot load page as of the moment.", Toast.LENGTH_SHORT).show();
return;
}
JsonArray rawStories = response.body();
if(rawStories.size() == 0) {
//TODO: show placeholder
return;
}
ArrayList<CuratedSectionItem> stories = new ArrayList<>();
for(int i = 0; i < rawStories.size(); i++) {
JsonObject jStories = rawStories.get(i).getAsJsonObject();
JSONObject temp = new JSONObject(jStories.toString());
JsonObject author = jStories.get("author").getAsJsonObject();
CuratedSectionItem story = new CuratedSectionItem();
story.title = jStories.get("title").getAsString();
story.avatar = author.get("profile_photo").getAsString();
story.displayPhoto = temp.getString("primary_photo");
story.username = author.get("username").getAsString();
story.description = jStories.get("content").getAsString();
story.topicId = jStories.get("id").getAsString();
story.postId = jStories.get("first_post_id").getAsString();
story.hasReacted = false;
story.upvotes = jStories.get("stats").getAsJsonObject().get("upvotes").getAsInt();
stories.add(story);
}
section.stories = stories;
} catch (IOException e) {
Log.d("ERROR!", e.toString());
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
这是发出异步请求并在线程中调用loadSectionStories
的方法:
public void loadCuratedSections(final int start, final int limit) {
SharedPreferences prefs = getSharedPreferences("user_session", MODE_PRIVATE);
final String sessionKey = prefs.getString("session_key", null);
Call<JsonArray> call;
call = TravelersApi.endpoint().getCuratedSections(sessionKey);
call.enqueue(new Callback<JsonArray>() {
@Override
public void onResponse(Call<JsonArray> call, Response<JsonArray> response) {
if(response.code() != 200) {
Toast.makeText(getApplicationContext(), "Cannot load page as of the moment.", Toast.LENGTH_SHORT).show();
return;
}
JsonArray rawSections = response.body();
if(rawSections.size() == 0) {
return;
}
for (int i = start; i < limit; i++) {
JsonObject jSection = rawSections.get(i).getAsJsonObject();
final CuratedSection section = new CuratedSection();
section.id = jSection.get("id").getAsString();
section.header = jSection.get("section_header").getAsString();
section.isShown = jSection.get("is_shown").getAsBoolean();
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
loadSectionStories(sessionKey, section);
}
});
thread.start();
curatedSections.add(section);
}
}
@Override
public void onFailure(Call<JsonArray> call, Throwable t) {
Log.d("ERROR!", t.toString());
t.printStackTrace();
}
});
}
一切正常,除了 section.stories
returns 为空。由于 loadSectionStories
中的语句 section.stories = stories
,这对我来说没有意义。
如果您在同步请求完成之前使用 section.stories(在新线程中为 运行),那么它将 return null 当前正在发生。
所以如果你想在你的第一个异步请求完成后使用它,你必须删除新的线程流,
或者您必须在故事更新时重新加载回收站视图。
还有你为什么在新线程中执行你的同步请求(loadSectionStories),这不是类似于异步请求吗?
Retrofit asyncRetrofit = new Retrofit.Builder()
.baseUrl(URLS.MAIN_SERVER_URL)
// below line create thread for syncrouns request
.callbackExecutor(Executors.newSingleThreadExecutor())
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build();
这将运行你的异步请求
我正在实施一个两级嵌套 recyclerView
,并且两个回收器视图都使用 retrofit
进行 API 调用。这是发出同步请求的方法:
public void loadSectionStories(String sessionKey, CuratedSection section) {
Call<JsonArray> subCall;
subCall = TravelersApi.endpoint().getCuratedSectionTopics(sessionKey, section.id);
try {
Response<JsonArray> response = subCall.execute();
if(response.code() != 200) {
Toast.makeText(getApplicationContext(), "Cannot load page as of the moment.", Toast.LENGTH_SHORT).show();
return;
}
JsonArray rawStories = response.body();
if(rawStories.size() == 0) {
//TODO: show placeholder
return;
}
ArrayList<CuratedSectionItem> stories = new ArrayList<>();
for(int i = 0; i < rawStories.size(); i++) {
JsonObject jStories = rawStories.get(i).getAsJsonObject();
JSONObject temp = new JSONObject(jStories.toString());
JsonObject author = jStories.get("author").getAsJsonObject();
CuratedSectionItem story = new CuratedSectionItem();
story.title = jStories.get("title").getAsString();
story.avatar = author.get("profile_photo").getAsString();
story.displayPhoto = temp.getString("primary_photo");
story.username = author.get("username").getAsString();
story.description = jStories.get("content").getAsString();
story.topicId = jStories.get("id").getAsString();
story.postId = jStories.get("first_post_id").getAsString();
story.hasReacted = false;
story.upvotes = jStories.get("stats").getAsJsonObject().get("upvotes").getAsInt();
stories.add(story);
}
section.stories = stories;
} catch (IOException e) {
Log.d("ERROR!", e.toString());
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
这是发出异步请求并在线程中调用loadSectionStories
的方法:
public void loadCuratedSections(final int start, final int limit) {
SharedPreferences prefs = getSharedPreferences("user_session", MODE_PRIVATE);
final String sessionKey = prefs.getString("session_key", null);
Call<JsonArray> call;
call = TravelersApi.endpoint().getCuratedSections(sessionKey);
call.enqueue(new Callback<JsonArray>() {
@Override
public void onResponse(Call<JsonArray> call, Response<JsonArray> response) {
if(response.code() != 200) {
Toast.makeText(getApplicationContext(), "Cannot load page as of the moment.", Toast.LENGTH_SHORT).show();
return;
}
JsonArray rawSections = response.body();
if(rawSections.size() == 0) {
return;
}
for (int i = start; i < limit; i++) {
JsonObject jSection = rawSections.get(i).getAsJsonObject();
final CuratedSection section = new CuratedSection();
section.id = jSection.get("id").getAsString();
section.header = jSection.get("section_header").getAsString();
section.isShown = jSection.get("is_shown").getAsBoolean();
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
loadSectionStories(sessionKey, section);
}
});
thread.start();
curatedSections.add(section);
}
}
@Override
public void onFailure(Call<JsonArray> call, Throwable t) {
Log.d("ERROR!", t.toString());
t.printStackTrace();
}
});
}
一切正常,除了 section.stories
returns 为空。由于 loadSectionStories
中的语句 section.stories = stories
,这对我来说没有意义。
如果您在同步请求完成之前使用 section.stories(在新线程中为 运行),那么它将 return null 当前正在发生。
所以如果你想在你的第一个异步请求完成后使用它,你必须删除新的线程流,
或者您必须在故事更新时重新加载回收站视图。
还有你为什么在新线程中执行你的同步请求(loadSectionStories),这不是类似于异步请求吗?
Retrofit asyncRetrofit = new Retrofit.Builder()
.baseUrl(URLS.MAIN_SERVER_URL)
// below line create thread for syncrouns request
.callbackExecutor(Executors.newSingleThreadExecutor())
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build();
这将运行你的异步请求