【问题标题】:postDelayed blocking ui threadpostDelayed阻塞ui线程
【发布时间】:2015-01-28 20:10:31
【问题描述】:

我想要什么:用户保持点击按钮 1900 毫秒。如果他在 1900 毫秒之前拿起手指,手机就会停止振动。而如果他将手指放在按钮上超过 1900 秒,calculate() 方法就会运行。 我正在使用:我读到的 postDelayed 不会干扰 ui 线程。 我试图检查是否已经过了 1900 秒,用户还没有拿起他的手指,即使是计算方法运行。 发生错误g:如果用户在 1900 秒前拨动手指,或者只是触摸并立即拨动,手机会一直振动。虽然它不应该发生,因为我正在使用 MotionEvent.ACTION_UP 检查它。请帮忙!!

  int flag = 0;
  int aborted_flag = 0;
 @Override
public boolean onTouch(View v, MotionEvent event) {

    Handler mHandler = new Handler();

    if(event.getAction()==MotionEvent.ACTION_DOWN){
        scanning();
        t1 = System.currentTimeMillis();
        vibrator.vibrate(1900);

        mHandler.postDelayed(new Runnable() {
            public void run() {
               check();
            }
        }, 1901);
    }

    if(event.getAction()==MotionEvent.ACTION_UP){
        if(flag == 0){
            t2 = System.currentTimeMillis();
            vibrator.cancel();
            calculate();
            aborted_flag = 1;
        }
    }

    return true;
}

private void check() {
    t2 = System.currentTimeMillis();
    Log.e("Hello","Inside Check");
    Log.e("Hello",""+aborted_flag);
    vibrator.cancel();
    if(aborted_flag==0){
        calculate();
        flag = 1;
    }
}

private void scanning() {
    textView.setText("Scanning");
}

private void calculate() {
    Log.e("t2-t1 ", t2-t1+"");

    if(t2-t1>=1900){
        Random r = new Random();
        int k = r.nextInt((5 - 0) + 1) + 0;
        textView.setText(str[k]);

        ////////////animation library code/////////////
        YoYo.with(Techniques.StandUp)
                .duration(700)
                .playOn(findViewById(R.id.text_view));
        ////////////////////////////////////////

        changeBackgroundColor(k);

        //textView.setTextColor(Color.parseColor("#00ff00"));
         flag = 0;
    }
    else{
        textView.setText("Aborted\n Try Again");
        relativeLayout.setBackgroundResource(R.color.red);
    }
}
public void changeBackgroundColor(final int k) {
    runOnUiThread(new Runnable(){
        public void run() {
            switch(k){
                case 0: relativeLayout.setBackgroundResource(R.color.blue);
                    break;
                case 1: relativeLayout.setBackgroundResource(R.color.pink);
                    break;
                case 2:;
                case 3: relativeLayout.setBackgroundResource(R.color.green);
                    break;
                default:relativeLayout.setBackgroundResource(R.color.yellow);
            }
        }
    });
}

【问题讨论】:

    标签: android button motionevent postdelayed


    【解决方案1】:

    如果您从 UI 线程调用 postDelayed,那么您的代码将在 UI 线程上执行。

    要使用不同的线程,请创建一个:

    Thread t = new Thread(new Runnable(){});
    t.start();
    

    【讨论】:

    • 但是如何等待1900ms
    • Thread t = new Thread(new Runnable(){ @Override public void run() { try{ Thread.sleep(1900); check(); } catch(Exception e){ e.printStackTrace (); } } }); t.start();但它没有帮助。但发生的情况是,如果他一直触摸手指,则计算方法不会运行
    【解决方案2】:

    您可以创建一个HandlerThread 并使用它的looper 创建一个处理程序,然后将内容发布到它postpostdelayed

    public class myActivity extends Activity
    {
        private HandlerThread loaderThread;
        private Handler loader;
    
        @override
        public void onResume()
        {
            super.onResume();
    
            if (loaderThread == null)
            {
                loaderThread = new HandlerThread("MyActivitySeparateThread");
                loaderThread.start();
                loader = new Handler(loaderThread.getLooper());
            }
        }
    
        @override
        public void onDestroy()
        {
            //Stop and release handler
            try {
                loader.removeCallbacksAndMessages(null);
                loader.dispose();
            } finally {
                loader = null;
            }
    
            //Stop and release Thread
            try {
                loaderThread.quit();
                loaderThread.dispose();
            } finally {
                loaderThread = null;
            }
    
            super.onDestroy();
        }
    
        @Override
        public boolean onTouch(View v, MotionEvent event)
        {
            switch(event.getAction())
            {
                case MotionEvent.ACTION_DOWN:
                    {
                        scanning();
                        t1 = System.currentTimeMillis();
                        vibrator.vibrate(1900);
    
                        loader.postDelayed(new Runnable()
                        {
                            public void run()
                            {
                                check();
                            }
                        }, 1901);
                        break;
                    }
                case MotionEvent.ACTION_UP:
                    {
                        if (flag == 0)
                        {
                            t2 = System.currentTimeMillis();
                            vibrator.cancel();
                            calculate();
                            aborted_flag = 1;
                        }
                        break;
                    }
            }
    
            return true;
        }
    }
    

    【讨论】:

      【解决方案3】:

      因为在 mHandler.postDelayed 中你调用 check(),它调用 calculate(),它调用 relativeLayout.setBackgroundResource()。 UI 只能从 UIThread 更改。

      制作函数:

      public void changeBackgroundColor(final int color) {
         runOnUiThread(new Runnable(){
              public void run() {
                 relativeLayout.setBackgroundResource(color);
                }
          });
      }
      

      然后从你的 calculate() 函数中调用它。

      【讨论】:

      • 我按照你说的编辑了代码,并通过添加 aborted_flag 做了一些小的改动。我想要的是,如果用户即使在 1900 毫秒后也没有选择手指,calculate() 方法就会运行并且屏幕颜色会发生变化。但实际情况是,如果他的手指一直触摸,则计算方法不会运行。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-17
      • 1970-01-01
      相关资源
      最近更新 更多