Here's some code that I used to accomplish something similar. In my example, I had to post JSON, then download and parse a JSON response and store the response in a SqLite database. You will need to adapt my code to your needs, but the concept is simple. The solution basically boils down to:
1) Parse the Json yourself using a JsonReader.
2) Use a FilterInputStream to publish progress.
I recognize that this solution doesn't use retrofit, so maybe you won't want to use it, but perhaps you will find it helpful.
final ProgressDialog dialog = new ProgressDialog(getActivity(), ProgressDialog.THEME_HOLO_LIGHT);
dialog.setTitle(R.string.downloading_data);
dialog.setMessage("Downloading data...");
dialog.setCanceledOnTouchOutside(false);
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
if (!BuildConfig.DEBUG) {
dialog.setProgressNumberFormat(null);
}
mLoginTask = new AsyncTask<Void, Integer, Void>() {
@Override
protected Void doInBackground(Void... params) {
HttpURLConnection connection = null;
try {
byte[] request = ...; // I used a JsonWriter to write to a ByteArrayOutputStream. Since you're likely getting this from file or a GET request, this is likely not necessary.
URL url = new URL("https://example.com/endpoint");
connection = (HttpURLConnection)url.openConnection();
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json; charset=utf-8");
connection.setRequestProperty("Content-Length", "" + request.length);
connection.setRequestProperty("Accept","*/*");
OutputStream out = connection.getOutputStream();
out.write(request);
out.flush();
out.close();
connection.setConnectTimeout(3000);
connection.setReadTimeout(10000);
connection.connect();
Thread.sleep(2000); // I don't remember why this was necessary. Likely an exception was thrown in the next line without it, at least on slower networks.
int responseCode = connection.getResponseCode();
switch (responseCode) {
case 200:
int length = connection.getContentLength();
publishProgress(0, length);
final InputStreamReader streamReader = new InputStreamReader(new FilterInputStream(connection.getInputStream()) {
private int mTotalBytesRead;
@Override
public int read() throws IOException {
int b = super.read();
if (b > 0) {
updateProgress(1);
}
return b;
}
@Override
public int read(byte[] buffer) throws IOException {
return updateProgress(super.read(buffer));
}
@Override
public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
return updateProgress(super.read(buffer, byteOffset, byteCount));
}
@Override
public long skip(long byteCount) throws IOException {
return updateProgress(super.skip(byteCount));
}
@Override
public void mark(int readLimit) {
throw new UnsupportedOperationException();
}
@Override
public void reset() throws IOException {
throw new UnsupportedOperationException();
}
@Override
public boolean markSupported() {
return false;
}
private int updateProgress(long numBytesRead) {
if (numBytesRead > 0) {
publishProgress(mTotalBytesRead += numBytesRead);
}
return (int)numBytesRead;
}
});
JsonReader reader = new JsonReader(streamReader);
// your code here will depend on the format of the code. It seems like you have simply an array.
reader.beginArray();
while (reader.peek() == JsonToken.BEGIN_OBJECT) {
JsonObject airport = (JsonObject) Streams.parse(reader);
// do some stuff with this airport. Perhaps create an Airport object and add it to an ArrayList.
}
return null;
default:
String response = IOUtils.toString(connection.getErrorStream());
try {
Util.showToast(JsonUtil.getString(new JSONObject(response), Constants.ERROR), Toast.LENGTH_LONG);
if (responseCode == 403) { // Forbidden
publishProgress();
}
} catch (Exception e) {
Util.showToast("Unsupported response\n" + connection.getHeaderField(null)+"\n"+response, Toast.LENGTH_LONG);
}
break;
}
} catch (UnknownHostException e) {
Util.showToast("You don't appear to be connected to the Internet.", Toast.LENGTH_LONG);
} catch (Exception e) {
if (e instanceof InterruptedIOException) {
return null;
}
Util.showToast(e.toString(), Toast.LENGTH_LONG);
Log.e("DashboardActivity", "error downloading data", e);
} finally {
if (connection != null) {
connection.disconnect();
}
}
return null;
}
@Override
protected void onPostExecute(Void result) {
dialog.cancel();
TaskUtil.synchronize(HomeFragment.this);
}
@Override
protected void onCancelled() {
dialog.cancel();
// todo: maybe you have more cleanup
}
@Override
protected void onProgressUpdate(Integer... values) {
if (values.length == 0) {
MyActivity.getCurrentActivity().showLoginInfo(true);
} else {
dialog.setProgress(values[0]);
if (values.length == 2) {
dialog.setMax(values[1]);
dialog.setIndeterminate(false);
dialog.show();
}
}
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
mLoginTask.cancel(true);
}
});