Inserting values to database in new thread causes progress dialog to dissmiss

206 views Asked by At

In my application I download a lot of data (around 3000-4000 records) from server and then insert it to database. The process takes very long time, so I want to show progress dialog while the whole process runs. I implemented the progress dialog inside of the AsyncTask class where I am downloading data and inserting it to database. Here is the code of AsyncTask:

    @Override
        protected void onPreExecute() {
            super.onPreExecute();
            a.runOnUiThread(new Runnable(){
                @Override
                public void run() {
                    pd.setTitle("Загрузка необходимых данных");
                    pd.setMessage("Пожалуйста подождите");
                    pd.setIndeterminate(true);
                    pd.setProgressStyle(ProgressDialog.STYLE_SPINNER);
                    pd.setProgress(0);
                    pd.setCancelable(false);
                    pd.show();
                }
            });

        }

        protected Map<String, String> doInBackground(String... strs) {
                    return getMaterials();
        }

        @Override
        protected void onPostExecute (Map<String, String> map) {
            a.runOnUiThread(new Runnable(){
                @Override
                public void run() {
                    pd.dismiss();
                }
            }); 
        }

public Map<String,String> getMaterials() {
        int maxNum = getMaxIndex("materials");
        Map<String,String> materials = null;
        DBConnection db = new DBConnection(context);
        Date end = new Date(System.currentTimeMillis());
        String exml = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" +
                "<REQUEST format=\"json\" client=\"exstroy\" action=\"get\" enddate=\""+ end.toString() + "\" " +
                "startdate=\"2000-01-28\" POINT_ID=\"3\" session=\"" + session_id + "\" catalogname=\"nomenclature\" type=\"cataloglist\">" +
                "<LIST firstmrid = \"0\" lastmrid=\""+ maxNum + "\"></LIST>"  +
                "</REQUEST>";
        try{
            PrintWriter writer = new PrintWriter(Environment.getExternalStorageDirectory().getPath() + "/data.xml", "UTF-8");
            writer.println(exml);
            writer.close();
        } catch (IOException e) {
        }

        String charset = "UTF-8";
        File uploadFile1 = new File(Environment.getExternalStorageDirectory().getPath() + "/data.xml");
        String requestURL = "blahblah.com";

        try {
            MultipartUtility multipart = new MultipartUtility(requestURL, charset);

            multipart.addFilePart("datafile", uploadFile1);

            List<String> response = multipart.finish();


            materials = new HashMap<String, String>();
            String s = "{ " + response.get(1) + "}";
            JSONObject json = new JSONObject(s);
            JSONObject cataloglist = json.getJSONObject("cataloglist");

            JSONArray array = cataloglist.names();
            //db.clearNomenclature();
            ArrayList<Map<String, Object>> data = new ArrayList<Map<String, Object>>(5000);
            int max = 0;
            for(int n = 0; n < array.length(); n++)
            {
                if (n > max)
                    max = n;
                JSONObject object = cataloglist.getJSONObject(array.getString(n));
                Map<String, Object> map;
                map = new HashMap<String, Object>();
                if (object.has("version"))
                    map.put("version", object.getInt("version"));
                else
                    map.put("version", 0);
                if (object.has("name"))
                    map.put("name", object.getString("name"));
                else
                    map.put("name", "");
                if (object.has("uuid"))
                    map.put("uuid", object.getString("uuid"));
                else
                    map.put("uuid", "");
                if (object.has("uuid"))
                    map.put("measure", object.getString("measure"));
                else
                    map.put("measure", "");

                data.add(map);

                }
          db.insertNom(data);
        } catch (IOException ex) {
            System.err.println(ex);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        ArrayList<Map<String, String>> measures = getMeasures();
        db.measures(measures);
        return materials;
    }

While downloading data is performed the progress dialog is showed, but when it reaches database insertion progress dialog is dismissed. Here is the part of the code for the database insertion:

public void insertNom(final ArrayList<Map<String, Object>> data) {
        dbOpen();
        database.execSQL("CREATE TABLE IF NOT EXISTS "+"nomenclature"+
                " ("+"ID"+" INTEGER PRIMARY KEY AUTOINCREMENT, "+
                "name TEXT, version INTEGER, measure UUID, uuid UUID)");
        dbClose();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < data.size(); i++) {
                    dbOpen();
                    Map<String, Object> map = data.get(i);
                    ContentValues cv = new ContentValues();
                    cv.put("name", (String) map.get("name"));
                    cv.put("version", (int) map.get("version"));
                    cv.put("uuid", (String) map.get("uuid"));
                    cv.put("measure", (String) map.get("measure"));
                    database.insert("nomenclature", null, cv);
                    dbClose();
                }
            }
        };
        new Thread(runnable).start();

    }

I tried to do it in a separate thread as you can see in the code above, also I have tried to do it just in the doInBackgroung method of AsyncTask. Both ways dismissed the progress dialog. Additionally there is one more issue, while downloading data from server is finished relatively fast: 3-4 seconds, inserting to database takes around 20 seconds, even more. Is there any way to do it faster? If not what causes the progress dialog to dismiss?

2

There are 2 answers

4
ρяσѕρєя K On BEST ANSWER

Around 3000-4000 records needed to insert in table. do following chnages to speed up insertion :

1. If data is inserted directly from JSON to table then no need to hold JSONObject's in HashMap. just use JsonReader which reads a JSON encoded value as a stream of tokens. and call insert method for every object. (Optional but if you do in current code then it will also reduce time of reading and packing data in Collection)

2. Use only doInBackground and remove Thread from insertNom method.

3. make bulk insert using Android db Transaction in doInBackground. like:

   protected Map<String, String> doInBackground(String... strs) {
        // 1. Open DB
        // 2. Create Table 

         Map<String, String> materials=getMaterials();

        // 3.
        // START Transaction
           database.beginTransaction();

         //call insertNom method
           insertNom(materials);

         // set Successful
         database.setTransactionSuccessful();

          // END Transaction 
         database.endTransaction();

         return materials;
    }
1
Jiyeh On

You don't need another Runnable Thread to do your db insert as it's already in the AsyncTask's doInBackground() which is running in a background thread.

Remove the Runnable block:

//Runnable runnable = new Runnable() {
//        @Override
//        public void run() {
            for (int i = 0; i < data.size(); i++) {
                dbOpen();
                Map<String, Object> map = data.get(i);
                ContentValues cv = new ContentValues();
                cv.put("name", (String) map.get("name"));
                cv.put("version", (int) map.get("version"));
                cv.put("uuid", (String) map.get("uuid"));
                cv.put("measure", (String) map.get("measure"));
                database.insert("nomenclature", null, cv);
                dbClose();
            }
//        }
//    };
// new Thread(runnable).start();

Hope this works!