Search code examples
androidpostcountdownlatch

CountDownLatch makes the app stop


I'm working around with CountDownLatch and I need to send two JSON to send on sequence.

I came out with this

   CountDownLatch countDownLatch = new CountDownLatch(1);
                try {
                    sendAndgetEODID(countDownLatch);
                    countDownLatch.await();
                    sendAndgetDispID();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

And inside of the sendAndGetEODID function is

private void sendAndgetEODID(final CountDownLatch countDownLatch) {

    Log.e("going to EOD", "going to EOD");

    JSONObject params = new JSONObject();

    try {
        params.put("company_id", CompanyID);
        params.put("subcompany_id", subCompID);
        params.put("control_no", control_no);
        params.put("trip_no", trip_no);
        params.put("bus_id", bus_id);
        params.put("conductor_id", conductor_id);
        params.put("driver_id", driver_id);
        params.put("driver2_id", null); //temporary
        params.put("device_serial", dev_serial);
        params.put("datetimestamp", datetimestamp);

        String baseUrl = null;

        final ConnectivityManager connMgr = (ConnectivityManager)
                mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
        final android.net.NetworkInfo wifi = connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
        final android.net.NetworkInfo mobile = connMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);

        if (wifi.isConnected()) {
            baseUrl = url1;
        } else if (mobile.isConnected()) {
            baseUrl = url2;
        }

        AndroidNetworking.post(baseUrl + "atts_eods")
                .addJSONObjectBody(params)
                .addHeaders("Content-Type", "application/json")
                .addHeaders("Prefer", "return=representation")
                .addHeaders("Accept", "application/vnd.pgrst.object+json")
                .setPriority(Priority.HIGH)
                .build()
                .getAsJSONObject(new JSONObjectRequestListener() {

                    @Override
                    public void onResponse(JSONObject response) {
                        Log.e("response EOD", String.valueOf(response));

                        try {
                            eod_return_id = String.valueOf(response.get("id"));

                            String queryEOD = ("update " + DBHelper.TRANS_EOD + " set " +
                                    DBHelper.TRANS_EOD_RETURN_ID + " = '" + eod_return_id +
                                    "', is_send = '1' where control_no = '" + control_no + "'");
                            sqldb.execSQL(queryEOD);

                            String updateTransSettingsEODID = ("update " + DBHelper.TRANS_SETTINGS + " set " +
                                    DBHelper.TRANS_EOD_RETURN_ID + " =  '" + eod_return_id +
                                    "' where control_no = '" + control_no + "'");

                            sqldb.execSQL(updateTransSettingsEODID);

                            String updateEODIDDispatch = ("update " + DBHelper.TRANS_DISPATCH + " set " +
                                    DBHelper.TRANS_DISPATCH_EOD_ID + " = '" + eod_return_id +
                                    "' where control_no = '" + control_no + "' and trip_no = '" + trip_no + "' ");

                            sqldb.execSQL(updateEODIDDispatch);


                            EODIDCatcher = eod_return_id;
                            Log.e("EODIDCatcher UP!", EODIDCatcher);

                            countDownLatch.countDown();

                        } catch (JSONException e) {
                            e.printStackTrace();
                            countDownLatch.countDown();
                        }
                    }

                    @Override
                    public void onError(ANError anError) {

                        Log.e("anError", "sending failed, it will generate a EODID222 \n" + anError.getErrorBody());

                        EODIDCatcher = generatedEODID;

                        String queryEOD = ("update " + DBHelper.TRANS_EOD + " set " + DBHelper.TRANS_EOD_RETURN_ID + " = '" + generatedEODID + "',is_send = '2' where control_no = '" + control_no + "' and trip_no = '" + trip_no + "' ");
                        sqldb.execSQL(queryEOD);

                        String updateEODIDDispatch = ("update " + DBHelper.TRANS_DISPATCH + " set " + DBHelper.TRANS_DISPATCH_EOD_ID + " = '" + generatedEODID + "' where control_no = '" + control_no + "' and trip_no = '" + trip_no + "' ");
                        sqldb.execSQL(updateEODIDDispatch);

                        String updateTransSettingsEODID = ("update " + DBHelper.TRANS_SETTINGS + " set " + DBHelper.TRANS_EOD_RETURN_ID + " =  '" + generatedEODID + "' where control_no = '" + control_no + "' and trip_no = '" + trip_no + "' ");
                        sqldb.execSQL(updateTransSettingsEODID);


                        Log.e("EODIDCatcher ERROR", EODIDCatcher);
                        countDownLatch.countDown();
                    }
                });
    } catch (Throwable e) {
        e.printStackTrace();
    }
}

May i know where is the error is? and its not going on my second function?. thanks!


Solution

  • It is blocked because your sendAndgetEODID(countDownLatch); won't run to completion. await causes the current thread to wait until the latch has counted down to zero. By the time you receive the response (which is asynchronous), countDownLatch.await(); will be triggered (since its synchronous) and cause the thread to wait.

    Solution:

    Approach 1:

    If your intention is to execute sendAndgetDispID(); after sendAndgetEODID(countDownLatch); call has been executed then simply replace countDownLatch.countDown(); with sendAndgetDispID(); as follows:

    new JSONObjectRequestListener() {
    
        @Override
        public void onResponse(JSONObject response) {
            Log.e("response EOD", String.valueOf(response));
    
            try {
                ...
                sendAndgetDispID();
    
            } catch (JSONException e) {
                e.printStackTrace();
                sendAndgetDispID();
            }
        }
    
        @Override
        public void onError(ANError anError) {
    
           ...
            sendAndgetDispID();
        }
    });
    

    Approach 2:

    Handle AndroidNetworking.post in different Thread. This might cause some multithreading issues, so you need to be careful and use synchronize block effectively.