1

我的代码可以完美运行,但前提是我两次单击该按钮。如果我只点击一次,它会返回“limit_customers”= 0。

@Override
    public void onClick(View v) {
        switch(v.getId()){
            case R.id.button_to_customers:
            int limit_customers = 50;
            // R1 = Radiobutton > inside RadioGroup

            if(r1.isChecked()){
                group_id = 0;
            }else{ group_id = 1;}

            if(the_list.get(0).getSelected() == true){
               Log.e("list:", String.valueOf(the_list.get(0).getSelected()));
               // This returns true at first click (it's correct)
               if(group_id == 0){
                  Log.e("group:", String.valueOf(group_id));
                  // returns 0 at first click (it's correct)
                  limit_customers = get_customers_count();
                  Log.e("limit:", String.valueOf(limit_customers));
                  // returns 0 at first click (it's INCORRECT) 
                  // at second click returns 3 (it's correct)

               }
            }
            break;
        }
    }

这是返回 count() 的函数;

public int get_customers_count(){
    ExecutorService mExec = Executors.newSingleThreadExecutor();
    mExec.execute(new Runnable() {
        @Override
        public void run() {             
            try{
                SoapObject request = new SoapObject(NAMESPACE, "get_count_customers");
                SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
                envelope.setOutputSoapObject(request);
                HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
                androidHttpTransport.call(URL + "/get_count_customers", envelope);

                SoapObject rep = (SoapObject) envelope.bodyIn;
                JSONArray jr = new JSONArray(rep.getPropertyAsString(0)); 
                JSONObject jb = (JSONObject) jr.get(0);  
                amount_customers = jb.getInt("count");
            }catch (Exception e){
                Log.e("Error:", e.toString());
            }
        }
    });
    return amount_customers;
}

任何人都知道它可能是什么?

编辑:我将所有答案都标记为正确,因为您的所有答案都是正确的,我根据它们解决了我的问题。谢谢你。

4

3 回答 3

1
return amount_customers;

将在您有机会对服务器执行代码之前调用(因为服务器调用在单独的线程中运行)。这就是为什么你得到 0,下次你点击你的按钮时,你会得到第一次调用的结果,第三次点击会得到第二次调用的结果,等等。

于 2013-10-18T11:40:40.117 回答
1

使用AsyncTask而不是线程,因为线程在后台运行,并且前台流程没有寻找/等待。

示例代码,

private class GetCustomersCont extends AsyncTask<Void, Void, Void> {
    private int amount_customers = 0;
    private ProgressDialog dialog=null;
    @Override
    protected void onPreExecute() {
        dialog = new ProgressDialog(this);
    dialog.setCancelable(false);
    dialog.setMessage("Please Wait..");
    dialog.show();
    }
    @Override
    protected Void doInBackground(Void... params) {
         try{
                SoapObject request = new SoapObject(NAMESPACE, "get_count_customers");
                SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
                envelope.setOutputSoapObject(request);
                HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
                androidHttpTransport.call(URL + "/get_count_customers", envelope);

                SoapObject rep = (SoapObject) envelope.bodyIn;
                JSONArray jr = new JSONArray(rep.getPropertyAsString(0)); 
                JSONObject jb = (JSONObject) jr.get(0);  
                amount_customers = jb.getInt("count");
            }catch (Exception e){
                Log.e("Error:", e.toString());
            }
        return null;
    }
    @Override
    protected void onPostExecute(Void result) {
         if(dialog.isShowing())
              dialog.dismiss();
         Log.e("limit:", String.valueOf(limit_customers));
    }
}

并更改onClick()为,

private GetCustomersCont mGetCustomersCont = null;


@Override
    public void onClick(View v) {
        switch(v.getId()){
            case R.id.button_to_customers:
            int limit_customers = 50;
            // R1 = Radiobutton > inside RadioGroup

            if(r1.isChecked()){
                group_id = 0;
            }else{ group_id = 1;}

            if(the_list.get(0).getSelected() == true){
               Log.e("list:", String.valueOf(the_list.get(0).getSelected()));
               // This returns true at first click (it's correct)
               if(group_id == 0){
                  Log.e("group:", String.valueOf(group_id));
                  mGetCustomersCont = new GetCustomersCont();
                  mGetCustomersCont.execute();
               }
            }
            break;
        }
    }
于 2013-10-18T12:03:09.780 回答
1

get_customers_count方法的实现执行一个异步可运行的来填充amount_customers。当您第一次单击 JSON 解析尚未完成时,类级别变量amount_customers保持为默认值(零)。在您的第一次和第二次单击 runnable 完成和行之间的某个时间点;

amount_customers = jb.getInt("count");

...正在运行。这意味着填充类变量会导致日志输出显示正确的值。重要的是,第二次单击启动了另一个异步任务,以第二次重新填充您看不到的 amount_customers 变量。

要直接获得答案,则需要同步调用。但是,正如您正确指出的那样,在 I/O 线程上对网络通信进行同步调用是坏消息(导致 ANR)。您可能需要某种 UI 小部件来指示正在获取 amount_customers 的值。当从解析任务返回值时,您将需要调用侦听器方法(您将其传递给 get_customers_count)以通知依赖于该值的代码可以安全地进行。在此期间,您还需要禁用按钮按下,因此不会发出进一步(重复)的请求。一个合理的 UI 应该是这样的;

非按下状态...(普通按钮)

_____________________
|                   |
|   Button label    |
|___________________|

单击后...(微调器通知用户正在发生某些事情 - 按钮已禁用)

_____________________
|                   |
| Button label {/}  |   ...{/} => spinner.
|___________________|

返回结果时....(普通按钮)

_____________________
|                   |
|   Button label    |
|___________________|

然后根据结果执行操作。

于 2013-10-18T11:49:34.570 回答