如何在不导致 UI 冻结的情况下延迟执行某项任务

How to delay performing a certain task without causing UI to freeze

所以我有一个 Asynctask class 在单击按钮 5 秒后执行下一个操作。

mButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            delay = new delayMessageAsyncTask();
            delay.setProgressBar(delaySendProgressWheel);
            delaySendProgressWheel.setProgress(0);
            delaySendProgressWheel.setSpinSpeed(0.21f);
            mButton.setVisibility(ImageView.GONE);
            delaySendProgressWheel.setVisibility(ProgressWheel.VISIBLE);
            delay.execute();

            //performAction();
        }
    });


class delayMessageAsyncTask extends AsyncTask<Void, Integer, Void> {
    int myProgress;
    @Override
    protected void onPreExecute() {
        myProgress = 0;
        super.onPreExecute();
    }

    @Override
    protected void onPostExecute(Void result) {
        edit_text.setText("");
        mButton.setVisibility(ImageView.VISIBLE);
        delaySendProgressWheel.setVisibility(ProgressWheel.GONE);
        msgAdapter.setArrayList(message);
        msgAdapter.notifyDataSetChanged();
        listView.smoothScrollToPosition(msgAdapter.getCount()-1);
        super.onPostExecute(result);
    }

    @Override
    protected Void doInBackground(Void... params) {
        while(myProgress<100){
            myProgress+=20;
            publishProgress(myProgress);
            try {
                Thread.sleep(1000);
            }catch(Exception e){
                e.printStackTrace();
            }
        }
        performAction();
        return null;
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
        delaySendProgressWheel.setProgress((float)values[0]);
    }

问题是,performAction() 非常复杂,因为它包含后台线程和 UI 线程,所以我必须在 doInBackground 中放一部分并更新 UI onPostExecute。但正如我所说,只有在恰好 5 秒后才能执行操作,因此它会在到达 onPostExecute 之前停止一段时间。我曾尝试将 performAction() 移动到 onPostExecute,但它会导致 UI 冻结。理想情况下,我想知道是否有任何方法可以在 onClick() 中的 execute() 方法之后停止执行代码,以便我可以将 performAction() 放在那里。

您可以在按下点击后使用处理程序添加延迟:

    Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
      public void run() {
        // exec code here
      }
    }, 5000);

你可以使用这个:

  Handler mHandler;

  public void postHandler() {
    mHandler = new Handler();
    mHandler.postDelayed(mRunnable, 5000);
  }

  private Runnable mRunnable = new Runnable() {

    @Override
    public void run() {
      /** Do something **/

        new AsyncTask<Void,Void,Void>(){

        @Override
        protected Void doInBackground(Void... params) {

            performAction();
            return null;
        }

       }.execute();
    }
  };