如何使用 Service 和 ASyncTask 轮询服务器并更新 UI

How to poll server using Service and ASyncTask and update UI

我目前正在使用 ZXing Barcode reader 扫描二维码。使用 API,ZXing 代码有一个 "onActivityResult()" 方法来处理成功或失败扫描。

如果成功,我会调用由 ASyncTask 组成的 checkQR class。目前它returns一次结果,因为它只在扫描后调用。

如何让calling/polling每隔30秒更新textView并在检测到某个文本(例如"it is done")后停止它(杀死服务)?

注意:CheckQR 构造函数接受 Context 和 TextView。 orderstatus 是我希望更新来自服务器的响应的 TextView。

onActivityResult() 的部分代码

public void onActivityResult(int requestCode, int resultCode, Intent intent) {
    IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
    if (scanResult != null) {
        String contents = scanResult.getContents();
        if (contents != null) {             
            orderNum.setText("Order Number: " + contents);
            new CheckQR(this,orderStatus).execute(contents);
        } else {
        //failed
        }
    }

你的问题有太多的注意事项。 您希望此调度程序将 运行 保持在 Activity 之外吗? 你想死板地每 30 秒调用一次 CheckQR,即使前一个还没有完成吗?

我假设您想在 Activity 存活期间一直调用 CheckQR,因为它会更新 TextView。 因此,如果您想在 CheckQR 完成后进行链式调用,那么您可以简单地使用 onPostExexute.

中的 Handler 递归执行此操作
private CheckQR cqr;

class CheckQR extends AsyncTask<Void, Void, String>{

    @Override
    protected String doInBackground(Void... voids) {
        if (isCancelled()){
            return null;
        }
        String res = httpCall();
        return res;
    }

    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        if (result == null || isCancelled() || result.equals("it is done")){
            return;
        }
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                cqr = new CheckQR();
                cqr.execute();
            }
        }, 30000);
    }
}

@Override
protected void onDestroy() {
    super.onDestroy();
    cqr.cancel(true);
}

如果你想每 30 秒启动一次 CheckQR,无论前一个是否完成,然后使用 ScheduledExecutorService

        ScheduledExecutorService scheduler =
            Executors.newSingleThreadScheduledExecutor();

        ScheduledFuture scheduledFuture = scheduler.scheduleAtFixedRate
            (new Thread(){

                @Override
                public void run() {
                    //do blocking http call

                    if(stopCondition)//when stop condition is met
                        scheduledFuture.cancel(false);

                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            if (!flagActivityOnDestroyedRaised){
                                // you need this flag to prevent 
                                // updating UI when Activity is already 
                                // destroyed
                                textView.setText("aaaa");
                            }

                        }
                    });
                }
            }, 0, 30, TimeUnit.SECONDS);

在 onDestroy 中清理

@Override
protected void onDestroy() {
    super.onDestroy();
    scheduledFuture.cancel(false);
    flagActivityOnDestroyedRaised = true; 
}

这段代码只是一个伪代码。您需要将此处的一些引用声明为实例变量并使用正确的方法。如果您使用 ScheduledExecutorService 那么您需要使用 runOnUiThread.

将 AsyncTask 解包到 Thread