循环执行网络调用后,同一项目被删除两次

Posted

技术标签:

【中文标题】循环执行网络调用后,同一项目被删除两次【英文标题】:The same item is being deleted twice after executing Network Call in a loop 【发布时间】:2016-03-23 17:46:10 【问题描述】:

我遇到了一个奇怪的问题。我正在尝试从mysql database 中删除选定的项目。虽然查询的所有内容都是正确的,并且我测试了查询并且它可以工作,但它不会从数据库中删除项目。

代码:

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();


设置方法:

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);
    

我在哪里执行任务:

@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;
        

回应:

    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'

虽然添加的名称是:[BLT Sandwich, Club Sandwich]

响应是最后一个对象的两倍:

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'

deleteDataWebService:

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

php 文件:

<?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");
?>

只有最后一项被删除。有什么想法吗?

【问题讨论】:

您是否测试过您的 API,是否可以正常工作? 是的,如果我执行原始查询,它工作正常 不是rawQuery,我问的是你创建的API? 是的,它可以工作....但是我不能删除多个选择...只有列表中的最后一个项目被删除 你需要修改你的API,删除多行。但是,顺便说一下这一行,您的代码是否可以正常工作? 【参考方案1】:

这是因为异步执行。调用 deleteDataWebService() 方法只会安排 DeleteData 任务的执行,不会立即执行。任务实际上是在一段时间后执行的。

假设你有两个项目要删除,在 for 循环中:

为 item1 设置了 nameAdapter, 任务计划执行, 为 item2 设置了 nameAdapter, 任务计划执行,

一段时间后

task 使用 item2 的 nameAdapter 执行, task 使用 item2 的 nameAdapter 执行,

将值作为参数传递给异步任务而不是通过 nameAdapter 共享变量传递将解决问题。 nameValuePairs 也不应该在任务实例之间共享。

例如:

    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);

【讨论】:

会尝试...所以你的意思是我设置名称值对的位置我应该作为参数传递我想要删除的内容吗? 我提供了一个例子 它可以工作,但我在从适配器中删除项目时遇到问题。你能帮帮我吗? 当然,但最好为此创建单独的问题。 我刚刚解决了...非常感谢,即使是最后一个人的帮助,是你【参考方案2】:

你的问题:

只有最后一项被删除。有什么想法吗?

更新查询:

DELETE FROM cart
 WHERE product_name='$productName'
   AND magazi_id='$magazi'
   AND servitoros_id='$servitoros'
   AND trapezi='$trapezi'
 order by id desc limit 1

【讨论】:

以上是关于循环执行网络调用后,同一项目被删除两次的主要内容,如果未能解决你的问题,请参考以下文章

Spring Task每次都会调用两次的问题

如何在运行时阻止forEach循环不执行两次?

gwt中的远程服务执行两次

maven项目中junit测试同一方法, 运行一次却重复执行了两次?

Quartz每次调度时被执行两次

同一个人在同一法院被两次曝光失信被执行人名单合理吗?