AsyncTask仅在调试器中逐步执行时执行

时间:2018-07-04 07:51:02

标签: android android-asynctask barcode-scanner

首先,我要说的是,我刚刚开始我的Android冒险,并且正在学习下面发布的代码。

因此,我有一个Zebra条形码扫描仪和一个Android设备,该设备可以处理扫描的条形码。这两个设备通过BT连接相互通信(我知道它正在工作)。 JsonObjectRequest正在处理扫描的条形码(也在工作)。根据外部服务的响应(或缺乏响应),扫描仪必须以某种方式做出反应:

绿色/红色LED亮-蜂鸣器-绿色/红色LED灭

这就是我在努力的地方:

如果我只有蜂鸣器-一切正常。如果我有一个LED亮/灭-只有LED亮。如果我有全部3个动作-没有一个动作被执行。

现在,奇怪的是,调试器显示了已接收和执行的动作

D/MainActivity: Barcode Received
I/ViewRootImpl: CPU Rendering VSync enable = false
I/BluetoothScanner: executeCommand started. opcode = DCSSDK_SET_ACTION inXML = <inArgs><scannerID>5</scannerID><cmdArgs><arg-int>45</arg-int></cmdArgs></inArgs>
I/BluetoothScanner: 7 SSI bytes sent: 0x05 0xE7 0x04 0x00 0x04 0xFF 0x0C 
I/BluetoothScanner: executeCommand returningDCSSDK_RESULT_SUCCESS
I/ViewRootImpl: CPU Rendering VSync enable = false
I/BluetoothScanner: executeCommand started. opcode = DCSSDK_SET_ACTION inXML = <inArgs><scannerID>5</scannerID><cmdArgs><arg-int>17</arg-int></cmdArgs></inArgs>
I/BluetoothScanner: 7 SSI bytes sent: 0x05 0xE6 0x04 0x00 0x11 0xFF 0x00 
I/BluetoothScanner: soundBeeper command write successful. Wait for Status.
                    executeCommand returningDCSSDK_RESULT_SUCCESS
I/ViewRootImpl: CPU Rendering VSync enable = false
I/BluetoothScanner: executeCommand started. opcode = DCSSDK_SET_ACTION inXML = <inArgs><scannerID>5</scannerID><cmdArgs><arg-int>46</arg-int></cmdArgs></inArgs>
I/BluetoothScanner: 7 SSI bytes sent: 0x05 0xE8 0x04 0x00 0x04 0xFF 0x0B 
                    executeCommand returningDCSSDK_RESULT_SUCCESS

我用来构造这些请求的代码是基于示例应用程序和Zebra see here the Zebra Android SDK提供的文档的,这就是我所说的那些动作的方式:

private class MyAsyncTask extends AsyncTask<String,Integer,Boolean> {
        int scannerId;
            StringBuilder outXML;
        DCSSDKDefs.DCSSDK_COMMAND_OPCODE opcode;
        private CustomProgressDialog progressDialog;

    public MyAsyncTask(int scannerId,  DCSSDKDefs.DCSSDK_COMMAND_OPCODE opcode){
        this.scannerId=scannerId;
        this.opcode=opcode;
        this.outXML = outXML;
    }
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        progressDialog = new CustomProgressDialog(MainActivity.this, "Execute Command...");
        progressDialog.show();
    }

    @Override
    protected Boolean doInBackground(String... strings) {
        return  executeCommand(opcode,strings[0],null,scannerId);
    }

    @Override
    protected void onPostExecute(Boolean b) {
        super.onPostExecute(b);
        if (progressDialog != null && progressDialog.isShowing())
            progressDialog.dismiss();
        if(!b){
            Toast.makeText(MainActivity.this, "Cannot perform the Action", Toast.LENGTH_SHORT).show();
        }
    }
}

@Override
    public boolean executeCommand(DCSSDKDefs.DCSSDK_COMMAND_OPCODE opCode, String inXML, StringBuilder outXML, int scannerID) {
        if (Application.sdkHandler != null)
        {
            if(outXML == null){
                outXML = new StringBuilder();
            }
            DCSSDKDefs.DCSSDK_RESULT result=Application.sdkHandler.dcssdkExecuteCommandOpCodeInXMLForScanner(opCode,inXML,outXML,scannerID);
            if(result== DCSSDKDefs.DCSSDK_RESULT.DCSSDK_RESULT_SUCCESS)
                return true;
            else if(result==DCSSDKDefs.DCSSDK_RESULT.DCSSDK_RESULT_FAILURE)
                return false;
        }
        return false;
    }

private final Handler dataHandler = new Handler(new Handler.Callback() {
    @Override
    public boolean handleMessage(Message msg) {

        switch(msg.what){
            case Constants.BARCODE_RECEIVED:
                Barcode barcode = (Barcode) msg.obj;
                sendApiHttpRequest(new String(barcode.getBarcodeData()));
                break;
        }
        return false;
    }
});

private void sendApiHttpRequest(String ticketId){
    String url = "https://#################################/" + ticketId;

    JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, url, null, myJsonListener(), myJsonErrorListener());

    // tag the request for ease of debugging
    jsonObjectRequest.setTag(TAG);

    // Access the RequestQueue through your singleton class.
    MySingleton.getInstance(this).addToRequestQueue(jsonObjectRequest);
}

private Response.Listener<JSONObject> myJsonListener() {

    return new Response.Listener<JSONObject>() {
        @Override
        public void onResponse(JSONObject response) {
            boolean status;

            try {
                status = response.getBoolean("status");
                if (status){
                    setScanResultOK();
                }else{
                    setScanResultERR();
                }
            }catch(JSONException e){
                setScanResultERR();
                Log.e(TAG, "Failure", e);
            }
        }
    };
}

private Response.ErrorListener myJsonErrorListener() {
    return new Response.ErrorListener() {

        @Override
        public void onErrorResponse(VolleyError error) {
            setScanResultERR();
            Log.i(TAG, "Error : " + error.getLocalizedMessage());
        }
    };
}

private void setScanResultOK(){
    prepareInXML(RMDAttributes.RMD_ATTR_VALUE_ACTION_LED_GREEN_ON);
    prepareInXML(RMDAttributes.RMD_ATTR_VALUE_ACTION_FAST_WARBLE_BEEP);
    prepareInXML(RMDAttributes.RMD_ATTR_VALUE_ACTION_LED_GREEN_OFF);

    TextView textViewScanResult = findViewById(R.id.txt_scan_result);
    textViewScanResult.setText(R.string.scan_res_ok);
    textViewScanResult.setTextAppearance(getApplicationContext(), R.style.roboto_medium_96dp_green);
}

private void setScanResultERR(){
    prepareInXML(RMDAttributes.RMD_ATTR_VALUE_ACTION_LED_RED_ON);
    prepareInXML(RMDAttributes.RMD_ATTR_VALUE_ACTION_LOW_LONG_BEEP_3);
    prepareInXML(RMDAttributes.RMD_ATTR_VALUE_ACTION_LED_RED_OFF);

    TextView textViewScanResult = findViewById(R.id.txt_scan_result);
    textViewScanResult.setText(R.string.scan_res_err);
    textViewScanResult.setTextAppearance(getApplicationContext(), R.style.roboto_medium_96dp_red);
}

private void performOpcodeAction(String inXML) {
    if (scannerID != -1) {
        new MyAsyncTask(scannerID, DCSSDKDefs.DCSSDK_COMMAND_OPCODE.DCSSDK_SET_ACTION).execute(new String[]{inXML});
    } else {
        Toast.makeText(this, "Invalid scanner ID", Toast.LENGTH_SHORT).show();
    }
}

private void prepareInXML(int value){
    String inXML = "<inArgs><scannerID>" + scannerID + "</scannerID><cmdArgs><arg-int>" +
            value + "</arg-int></cmdArgs></inArgs>";
    performOpcodeAction(inXML);
}

当我设置断点并逐步执行代码时,所有动作都将执行,并且在我运行该应用程序后,就会遇到这些问题。

有人可以帮助我吗?

1 个答案:

答案 0 :(得分:0)

这是我从您的代码中了解的内容。您正在将HTTP请求发送到服务器,并基于响应,将执行一系列事件,例如LED和声音状态切换。

作为后台,Asynctask用于在后台线程上执行一段代码。在您的情况下,您想执行命令。顾名思义,它们是异步的,将与您的主线程(至少是doInBackground)并行运行。

setScanResultOKsetScanResultERR中,您可能实例化了3个异步任务。默认情况下,其中只有一个默认运行,asynctasks在单个执行线程上运行。如果要完全运行它们,请在线程池执行程序中执行它们。

现在,您提到要按顺序运行它们。我建议这样重构您的代码。

  1. 创建2个异步任务,其中1个成功,1个错误。
  2. 在doInBackground中执行多个prepareInXML调用
  3. 根据响应实例化一个异步任务,然后执行。

例如:

@Override
protected Boolean doInBackground(String... strings) {
    if (!prepareInXML(RMDAttributes.RMD_ATTR_VALUE_ACTION_LED_GREEN_ON)) {
        return false;
    }
    if (!prepareInXML(RMDAttributes.RMD_ATTR_VALUE_ACTION_FAST_WARBLE_BEEP)) {
        return false;
    }
    return prepareInXML(RMDAttributes.RMD_ATTR_VALUE_ACTION_LED_GREEN_OFF);
}

当然,这将需要您更改一些函数签名以适应。然后在onPostExecute中处理所有UI更改。

@Override
protected void onPostExecute(Boolean b) {
    super.onPostExecute(b);
    if (progressDialog != null && progressDialog.isShowing())
        progressDialog.dismiss();
    if(!b){
        Toast.makeText(MainActivity.this, "Cannot perform the Action", Toast.LENGTH_SHORT).show();
    }
    /* perform UI changes particular to the type of task (success/fail) */
}

更新: 尝试在命令之间添加延迟。 no op可能实际上是一个断断续续的序列,我们很快注意到了。