The same item is being deleted twice after running Network Call in a loop

advertisements

I am facing a strange problem. I am trying to delete the selected items from the mysql database. Though everything for the query is correct and i tested the query and it works but it does not delete items from database.

The code:

private class DeleteData extends AsyncTask<String, Void, List<CartList>> {

@Override
protected void onPreExecute() {
    super.onPreExecute();
    progressDialog = new ProgressDialog(CartActivity.this);
    progressDialog.setMessage(getString(R.string.get_stocks));
    progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
    progressDialog.setIndeterminate(true);
    progressDialog.setCancelable(false);
    progressDialog.show();
}

@Override
protected List<CartList> doInBackground(String... params) {
    nameValuePairs = new ArrayList<>();
    cartItems = new ArrayList<>();
    try {
        url = new URL(params[0]);
        httpURLConnection = (HttpURLConnection) url.openConnection();
        httpURLConnection.setReadTimeout(10000);
        httpURLConnection.setConnectTimeout(15000);
        httpURLConnection.setRequestMethod("POST");
        httpURLConnection.setDoInput(true);
        httpURLConnection.setDoOutput(true);
        deleteDataInDB();
        outputStream = httpURLConnection.getOutputStream();
        bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
        bufferedWriter.write(StringGenerator.queryResults(nameValuePairs));
        bufferedWriter.flush();
        bufferedWriter.close();
        outputStream.close();
        httpURLConnection.connect();
        inputStream = new BufferedInputStream(httpURLConnection.getInputStream());
        jsonResult = StringGenerator.inputStreamToString(inputStream, CartActivity.this);
        Log.e("Response: ", jsonResult.toString());
    } catch (IOException e) {
        e.printStackTrace();
    }

    return cartItems;
}

@Override
protected void onPostExecute(List<CartList> cartLists) {
    super.onPostExecute(cartLists);
    progressDialog.dismiss();
}
}

The setup Method:

private void deleteDataInDB(){

        nameValuePairs.add(new BasicNameValuePair(AppConstant.PRODUCT_NAME_VALUE_PAIR, nameAdapter));
        Log.e("Name Adapter Value: ", nameAdapter);
        nameValuePairs.add(new BasicNameValuePair(AppConstant.COMPANY_INTENT_ID, magazi_id));
        Log.e("Magazi id: ", magazi_id);
        nameValuePairs.add(new BasicNameValuePair(AppConstant.PRODUCT_WAITER_ID_VALUE_PAIR, servitoros_id));
        Log.e("Servitoros id: ", servitoros_id);
        nameValuePairs.add(new BasicNameValuePair(AppConstant.PRODUCT_TABLE_ID_VALUE_PAIR, table));
        Log.e("Table: ", table);
    }

Where i execute the task:

@Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            switch (item.getItemId()){
                case R.id.deleteCartItemModification:{
                    for (int position = 0; position<names.size(); position++){
                        nameAdapter = names.get(position);
                        deleteDataWebService();
                        adapter.notifyItemRemoved(position);
                    }
                    setupTotalValue();
                    Toast.makeText(CartActivity.this, "Items Deleted", Toast.LENGTH_SHORT).show();
                    adapter.notifyDataSetChanged();
                    AlertDialog.Builder builder = new AlertDialog.Builder(CartActivity.this);
                    builder.setTitle(getString(R.string.delete));
                    builder.setMessage(getString(R.string.delete_msg));
                    builder.setPositiveButton(getString(R.string.yes), new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            deleteDataWebService();
                            Toast.makeText(CartActivity.this, "Items Deleted", Toast.LENGTH_SHORT).show();
                            adapter.notifyDataSetChanged();
                        }
                    });
                    builder.setNegativeButton(getString(R.string.no), new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.cancel();
                        }
                    });
                    builder.create();
                    builder.show();
                }
            }
            return true;
        }

The response:

    12-17 05:37:24.043 2099-2099/com.order.app.order E/Names Added:: [BLT Sandwich, Club Sandwich]
12-17 05:37:24.045 2099-2099/com.order.app.order I/AppCompatDelegate: The Activity's LayoutInflater already has a Factory installed so we can not install AppCompat's
12-17 05:37:24.086 2099-2118/com.order.app.order W/EGL_emulation: eglSurfaceAttrib not implemented
12-17 05:37:24.086 2099-2118/com.order.app.order W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0xa0883cc0, error=EGL_SUCCESS
12-17 05:37:26.390 2099-2118/com.order.app.order D/OpenGLRenderer: endAllStagingAnimators on 0xa1ce1b00 (RippleDrawable) with handle 0xa18d8700
12-17 05:37:26.417 2099-2123/com.order.app.order E/Response:: DELETE FROM cart WHERE product_name='Club Sandwich' AND magazi_id='53' AND servitoros_id='724' AND trapezi='3'
12-17 05:37:26.430 2099-2118/com.order.app.order W/EGL_emulation: eglSurfaceAttrib not implemented
12-17 05:37:26.430 2099-2118/com.order.app.order W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0xa0883cc0, error=EGL_SUCCESS
12-17 05:37:26.445 2099-2123/com.order.app.order E/Response:: DELETE FROM cart WHERE product_name='Club Sandwich' AND magazi_id='53' AND servitoros_id='724' AND trapezi='3'

While the Names Added is: [BLT Sandwich, Club Sandwich]

The response is twice the last object:

E/Response:: DELETE FROM cart WHERE product_name='Club Sandwich' AND magazi_id='53' AND servitoros_id='724' AND trapezi='3'
E/Response:: DELETE FROM cart WHERE product_name='Club Sandwich' AND magazi_id='53' AND servitoros_id='724' AND trapezi='3'

The deleteDataWebService:

private void deleteDataWebService(){
        DeleteData deleteData = new DeleteData();
        deleteData.execute(AppConstant.DELETE_URL);
    }

The PHP File:

<?php
ini_set("default_charset", "UTF-8");
    header('Content-type: text/html; charset=UTF-8');
try {
    $handler = new PDO('mysql:host=my_server;dbname=database', 'username', 'password');
        $handler->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES utf8 ");
    $handler->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $handler->exec("SET CHARACTER SET 'utf8'");
} catch (Exception $e) {
    echo $e->getMessage();
    die();
}
$productName = $_POST['productName'];
$magazi = $_POST['magazi_id'];
$servitoros = $_POST['servitoros_id'];
$trapezi = $_POST['trapezi'];
$handler->query("DELETE FROM cart WHERE product_name='$productName' AND magazi_id='$magazi' AND servitoros_id='$servitoros' AND trapezi='$trapezi'");
die("Deleted");
?>

And only the last item is being deleted. Any ideas?


It is because of asynchronous execution. Calling deleteDataWebService() method only schedules execution of DeleteData task, does not execute it instantly. Task is actually performed some time later.

Assume that you have two items to delete, in for loop:

  • nameAdapter set for item1,
  • task is scheduled to execute,
  • nameAdapter set for item2,
  • task is scheduled to execute,

Some time later

  • task is executed with nameAdapter for item2,
  • task is executed with nameAdapter for item2,

Passing value as parameter to async task instead of passing it via nameAdapter shared variable will solve the problem. Also nameValuePairs should not be shared between task instances.

e.g:

    private class DeleteData extends AsyncTask<String, Void, List<CartList>> {
    ArrayList<BasicNameValuePair> nameValuePairs;

    private void deleteDataInDB(String name){
        nameValuePairs.add(new BasicNameValuePair(AppConstant.PRODUCT_NAME_VALUE_PAIR, name));
        ...
    }
    ...

    @Override
    protected List<CartList> doInBackground(String... params) {
        ...
        deleteDataInDB(params[1]);
        ...
    }

    ...
}

private void deleteDataWebService(String name){
    DeleteData deleteData = new DeleteData();
    deleteData.execute(AppConstant.DELETE_URL, name);
}