如何在不挂起UI的情况下模拟Android上的客户端延迟?

时间:2012-10-16 14:43:47

标签: java android unit-testing testing

我有一个与后端Web服务对话的Androd应用程序。作为测试的一部分,我需要在按下提交按钮时模拟不同长度的客户端延迟。<​​/ p>

现在,我在我的OnClickListener中使用Thread.sleep()作为我的提交按钮,但是像这样睡眠UI线程会导致应用程序看起来完全“冻结” - 按钮保持突出显示直到线程醒来并且我的ProgressBar同样被完全冻结。这是我的代码:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_checkout);

    pBar = (ProgressBar) findViewById(R.id.progressBar1);
    pBar.setVisibility(View.INVISIBLE);

    Button submitButton = (Button) findViewById(R.id.btnSubmit);
    submitButton.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            pBar.setVisibility(View.VISIBLE);
            try {
                Thread.sleep(3000); //eventually this delay will be random
                                    //right now it obviously hangs the UI
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            performMyAppSpecificWorkHere();
            pBar.setVisibility(View.INVISIBLE);
            CheckoutActivity.this.finish();
        }
    });  
}

我正在寻找可以在不挂起整个UI的情况下模拟延迟的方法。欢迎任何想法。谢谢!

修改

这里有一些说明!我需要做的部分是模拟延迟并允许用户界面干净地处理它(这是现在没有发生的事情)。

即...如果客户端或Web服务有延迟,客户端应该通过让spinner在等待时旋转来处理它。模拟后端延迟的能力已经完成,并且按我想要的方式工作,但我想在不挂起UI线程的情况下模拟客户端上的延迟。

3 个答案:

答案 0 :(得分:4)

我们走了:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_checkout);

    pBar = (ProgressBar) findViewById(R.id.progressBar1);
    pBar.setVisibility(View.INVISIBLE);

    Button submitButton = (Button) findViewById(R.id.btnSubmit);
    submitButton.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {

            Thread t=new Thread(new Runnable(){
               @Override
               public void run(){
                 try {
                  Thread.sleep(3000);
                 } catch (InterruptedException e) {
                   e.printStackTrace();
                 }
                 performMyAppSpecificWorkHere();
                 runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        pBar.setVisibility(View.INVISIBLE);
                        CheckoutActivity.this.finish();
                    }
                 }
               }
            });
            pBar.setVisibility(View.VISIBLE);
            t.start();
        }
    });  
}

因此,您正在onClick事件中启动一个新线程。这个新线程应该在睡眠3秒后进行应用程序工作。之后,您想要更新一些ui对象,而不能从不是UI线程的线程内部执行此操作。这就是执行工作后有runOnUiThread(..)的原因。希望它有所帮助!

答案 1 :(得分:3)

首先,不要阻塞主线程(ui-thread),否则gui会被冻结!相反,使用AsyncTask,将Thread.sleep(3000)置于doInBackground()内,然后在onPostExecute()内执行任何操作(onPostExecute()正在主线程中运行)。在相关问题上查看my last answer

答案 2 :(得分:0)

我认为你应该在这里澄清,你想模拟服务器端延迟而不是客户端延迟。您应该将睡眠代码放在服务器端代码中,而不是客户端代码。

如果不是这样,您可以使用asyncTask并执行应用程序代码。您可以将睡眠代码放入其中以模拟客户端延迟。<​​/ p>