0

I have an application which perform many files download from a server, decode the file content (json format) and save it into realm database. It's an utility app for our customers and need to work offline, so it has to store a lot of information.

For doing that, I have a "sync" page where I perform all my web queries (20+).

My problem is that the full operation takes about 5 minutes, while I see many games downloading 500+Mb of datas and storing them nearly istantly.

I'm going to post the longest asyncTask I have which takes about 2 minutes to finish.

this is my object

public class Meter extends RealmObject {

  public Meter(){}

  @PrimaryKey
  private String ID;

  @Index
  private String MARCA;
  @Index
  private String MATRICOLA;

  private String NUMERO_CIFRE;
  private String DIAMETRO;
  private String SIGILLO;
  private String NUMERO_LOTTO;
  private String LUNGHEZZA;
  private String COEFFICIENTE;
  private String ID_ARTICOLO;
  private Item articolo;
  //...
}

I download it using this asyncTask:

public static class DownloadMetersAsyncTask extends AsyncTask<String, Integer, Boolean> {

    private String newSha;
    private GenericDbClassMethods genericDbClass;
    //asyncTaskItem is just an object keeping my file info to identify it on server side like file name
    private AsyncTaskSyncItem asyncTaskSyncItem;
    //this is an interface that I use for handling the start-update-finish events
    private IReturnFinishAndStatusToParent iReturnFinishAndStatusToParent;

    private synchronized void setProgress(int progress) {
        asyncTaskSyncItem.setProgress(progress);
        iReturnFinishAndStatusToParent.onProgressUpdate(progress);
    }

    public DownloadMetersAsyncTask(Context ctx, AsyncTaskSyncItem asyncTaskSyncItem, IReturnFinishAndStatusToParent iReturnFinishAndStatusToParent) {
        this.asyncTaskSyncItem = asyncTaskSyncItem;
        this.iReturnFinishAndStatusToParent = iReturnFinishAndStatusToParent;
        this.genericDbClass = new GenericDbClassMethods(ctx);
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
        setProgress(values[0]);
    }

    @Override
    protected Boolean doInBackground(String... params) {
        Realm realm = null;
        final boolean[] ok = {true};
        newSha = null;
        try {
            realm = Realm.getDefaultInstance();
            publishProgress(5);
            String url = "...";
            OkHttpClient client = new OkHttpClient.Builder()
                    .connectTimeout(600, TimeUnit.SECONDS)
                    .writeTimeout(600, TimeUnit.SECONDS)
                    .readTimeout(600, TimeUnit.SECONDS)
                    .retryOnConnectionFailure(true)
                    .build();
            publishProgress(10);
            Request request = new Request.Builder().url(url)
                    .addHeader("Content-Type", "application/json")
                    .addHeader("Connection", "close")
                    .build();
            publishProgress(15);
            Response response = client.newCall(request).execute();
            publishProgress(20);

            ResponseBody responseBody = response.body();
            publishProgress(25);
            try {
                String myHeader = response.header("Content-Disposition");
                if (myHeader != null) {
                    int position = myHeader.indexOf("filename=");
                    position += "filename=".length();
                    newSha = myHeader.substring(position);
                }
            } catch (Exception ex) {
                newSha = null;
            }
            if (responseBody == null) {
                return true;
            }
            final BufferedInputStream is = new BufferedInputStream(responseBody.byteStream());

            publishProgress(45);
            realm.executeTransaction(new Realm.Transaction() {
                @Override
                public void execute(Realm realm) {
                    try {
                        Log.d("SYNC", "Meter - start delete");
                        realm.delete(Meter.class);
                        Log.d("SYNC", "Meter - end delete, start create");
                        realm.createAllFromJson(Meter.class, is);

                        publishProgress(100, 1);
                        genericDbClass.setSHA(realm, new Meter(), newSha); //another stuff, really fast, can be removed
                    } catch (Exception error) {
                        error.printStackTrace();
                        newSha = null;

                        ok[0] = false;
                        publishProgress(100, 0);
                        publishProgress(75);
                    }
                }
            });
            is.close();
            response.close();

        } catch (IOException error) {
            newSha = null;
            publishProgress(100, 0);
        } finally {
            if (realm != null) {
                realm.close();
            }
        }
        return ok[0];
    }

    @SuppressWarnings("unchecked")
    @Override
    protected void onPostExecute(Boolean v) {
        iReturnFinishAndStatusToParent.onFinish(v);
    }
}

This code works, the problem is that even if the download takes some seconds, the database insert is taking 1-2 minutes and this is way to much.

I was wondering if there might be a better way for handling the operation like performing the insert async.

Thanks in advice

Edit, add timers (just checked)

  • It takes less than 1 second to go from onPreExecute to realm.createAllFromJson(Meter.class, is) (excluded).
  • Performing realm.createAllFromJson(Meter.class, is) takes 3 minutes 50 seconds
Pier Giorgio Misley
  • 5,305
  • 4
  • 27
  • 66

0 Answers0