改造 - 如何在异步请求中发出同步请求

时间:2017-12-26 06:10:48

标签: android asynchronous android-recyclerview retrofit2 synchronous

我实现了两级嵌套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返回null之外,一切正常。由于section.stories = stories内的loadSectionStories声明,对我来说没有意义。

2 个答案:

答案 0 :(得分:0)

如果在同步请求完成之前使用section.stories(在新线程中运行),那么它将返回当前正在发生的null。

因此,如果要在第一次异步请求完成后使用它,则必须删除新的线程流,

或者在更新故事时必须重新加载回收站视图。

另外,为什么要在新线程中执行同步请求(loadSectionStories),它是否与异步请求不相似?

答案 1 :(得分:0)

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

这将在asyncronous

中运行您的请求