2

I've use this code to download Json file and convert it to my project. Since there are 40k items to download I need to add a % of the download of this file. My code is:

        final Retrofit retrofit = new Retrofit.Builder()
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
            .baseUrl(AirportService.SERVICE_ENDPOINT).build();


    AirportService service = retrofit.create(AirportService.class);

    service.getAirport()
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<List<Airport>>()
            {
                @Override
                public void onCompleted()
                {

                }

                @Override
                public void onError(Throwable e)
                {
                    e.printStackTrace();
                }

                @Override
                public void onNext(List<Airport> airports)
                {
                    airps = airports;
                }
            });

but I'm at the beginning of retrofit and I don't know to do it. Anyone could help me? Thanks

nani
  • 382
  • 5
  • 15

1 Answers1

0

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);
    }
});
Tim Cooke
  • 862
  • 7
  • 14