Close OkHttp request before making new ones

When adding certain podcasts [1], a `LeakedClosableViolation` is thrown
due to the fact that we're reusing the OkHttpClient to make multiple
requests (one to get the iTunes toplist for the user's language, and
another one defaulting to US).

This makes sure that all requests are closed to prevent this exception,
according to OkHttp docs [2].

[1]: https://podcasts.apple.com/us/podcast/stupid-genius-with-emma-chamberlain/id1458568923
[2]: https://github.com/square/okhttp/blob/18f2b5e/okhttp/src/main/java/okhttp3/Call.kt#L32-L40
This commit is contained in:
Anderson Mesquita 2019-04-27 12:47:23 -04:00
parent a4dc3d9e96
commit 34d33f796e
1 changed files with 36 additions and 30 deletions

View File

@ -238,42 +238,19 @@ public class ItunesSearchFragment extends Fragment {
progressBar.setVisibility(View.VISIBLE); progressBar.setVisibility(View.VISIBLE);
disposable = Single.create((SingleOnSubscribe<List<Podcast>>) emitter -> { disposable = Single.create((SingleOnSubscribe<List<Podcast>>) emitter -> {
String lang = Locale.getDefault().getLanguage(); String lang = Locale.getDefault().getLanguage();
String url = "https://itunes.apple.com/" + lang + "/rss/toppodcasts/limit=25/explicit=true/json";
OkHttpClient client = AntennapodHttpClient.getHttpClient(); OkHttpClient client = AntennapodHttpClient.getHttpClient();
Request.Builder httpReq = new Request.Builder() String feedString;
.url(url)
.header("User-Agent", ClientConfig.USER_AGENT);
List<Podcast> results = new ArrayList<>();
try { try {
Response response = client.newCall(httpReq.build()).execute(); try {
if(!response.isSuccessful()) { feedString = getTopListFeed(client, lang);
// toplist for language does not exist, fall back to united states } catch (IOException e) {
url = "https://itunes.apple.com/us/rss/toppodcasts/limit=25/explicit=true/json"; feedString = getTopListFeed(client, "us");
httpReq = new Request.Builder()
.url(url)
.header("User-Agent", ClientConfig.USER_AGENT);
response = client.newCall(httpReq.build()).execute();
}
if(response.isSuccessful()) {
String resultString = response.body().string();
JSONObject result = new JSONObject(resultString);
JSONObject feed = result.getJSONObject("feed");
JSONArray entries = feed.getJSONArray("entry");
for(int i=0; i < entries.length(); i++) {
JSONObject json = entries.getJSONObject(i);
Podcast podcast = Podcast.fromToplist(json);
results.add(podcast);
}
}
else {
String prefix = getString(R.string.error_msg_prefix);
emitter.onError(new IOException(prefix + response));
} }
List<Podcast> podcasts = parseFeed(feedString);
emitter.onSuccess(podcasts);
} catch (IOException | JSONException e) { } catch (IOException | JSONException e) {
emitter.onError(e); emitter.onError(e);
} }
emitter.onSuccess(results);
}) })
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
@ -291,6 +268,35 @@ public class ItunesSearchFragment extends Fragment {
}); });
} }
private String getTopListFeed(OkHttpClient client, String language) throws IOException {
String url = "https://itunes.apple.com/%s/rss/toppodcasts/limit=25/explicit=true/json";
Request.Builder httpReq = new Request.Builder()
.header("User-Agent", ClientConfig.USER_AGENT)
.url(String.format(url, language));
try (Response response = client.newCall(httpReq.build()).execute()) {
if (response.isSuccessful()) {
return response.body().string();
}
String prefix = getString(R.string.error_msg_prefix);
throw new IOException(prefix + response);
}
}
private List<Podcast> parseFeed(String jsonString) throws JSONException {
JSONObject result = new JSONObject(jsonString);
JSONObject feed = result.getJSONObject("feed");
JSONArray entries = feed.getJSONArray("entry");
List<Podcast> results = new ArrayList<>();
for (int i=0; i < entries.length(); i++) {
JSONObject json = entries.getJSONObject(i);
results.add(Podcast.fromToplist(json));
}
return results;
}
private void search(String query) { private void search(String query) {
if (disposable != null) { if (disposable != null) {
disposable.dispose(); disposable.dispose();