2017-08-25 105 views
0

我已经写了一个菜单为多个按钮的应用程序。其中两个按钮触发两种独立的蓝牙方法。问题是,在多次快速按下这些按钮时,应用程序崩溃,因为每种方法都试图管理蓝牙连接(而另一个可能会关闭该连接)。我试图在任何方法运行时检查变量'true'并检查它,但它不起作用。我不确定系统是否在不同的线程中同时运行每种方法,或者是否将方法排入队列。停止方法从执行按钮按

问题是,在另一个方法执行时,我该如何停止按下按钮来运行方法?执行完成后我不需要排队,我只需要将其阻塞即可。

编辑:添加的以下方法之一的代码,如请求(另一个是相同的,两个字符串,这是不相关的在此上下文中的除外):

public void lock(View button_lock) { 
     if(ok) 
      return; 
     if (btAdapter == null) { 
      Context context = getApplicationContext(); 
      CharSequence text = "Bluetooth not supported!"; 
      int duration = Toast.LENGTH_SHORT; 
      Toast toast = Toast.makeText(context, text, duration); 
      toast.show(); 
      return; 
     } 
     else if (address == null) { 
      Context context = getApplicationContext(); 
      CharSequence text = "Please pair your phone with SmartLock."; 
      int duration = Toast.LENGTH_SHORT; 
      Toast toast = Toast.makeText(context, text, duration); 
      toast.show(); 
      return; 
     } 
     if (!btAdapter.isEnabled()) { 
      btAdapter.enable(); 
      ok=true; 
     } 
     mHandler.postDelayed(new Runnable() {public void run() { 
      BluetoothDevice device = btAdapter.getRemoteDevice(address); 
      ParcelUuid[] uuids = device.getUuids(); 
      BluetoothSocket mmSocket; 
      try { 
       mmSocket = device.createRfcommSocketToServiceRecord(uuids[0].getUuid()); 
       mmSocket.connect(); 
       OutputStream out = mmSocket.getOutputStream(); 
       InputStream in = mmSocket.getInputStream(); 
       out.write("1".getBytes()); 
       try { 
        Thread.sleep(1000); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
       in.close(); 
       out.close(); 
       mmSocket.close(); 
       in = null; 
       out = null; 
       mmSocket = null; 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     }}, 1000); 
     Context context = getApplicationContext(); 
     CharSequence text = "Bike locked!"; 
     int duration = Toast.LENGTH_SHORT; 
     Toast toast = Toast.makeText(context, text, duration); 
     toast.show(); 
     mHandler.postDelayed(new Runnable() {public void run() { 
      try { 
       Thread.sleep(1000); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
      btAdapter.disable(); 
      ok=false; 
     }}, 2000); 
    } 

回答

1

正如你已经尝试过它与布尔,semaphore可以在这里做的伎俩。

0

试试这个:

bluetoothMethod(); 
    bluetoothButton.setEnabled(false); 
    new Handler().postDelayed(new Runnable() { 
     @Override 
     public void run() { 
      bluetoothButton.setEnabled(true); 
     } 
    }, duration); 

(在milis持续时间)

+0

这不能解决问题,只会拖延行动,这是一个不好的方法来处理这个问题,请参阅@Patrick Michel回答以获得更好的处理方法 –

0

不能在onClick()通过禁用按钮解决的,因为Android的事件系统的工作方式这个问题。当用户按下按钮时,“点击”事件排队到事件队列。如果用户快速连续两次按下按钮(特别是在低端设备上或UI线程繁忙时),则2个“单击”事件将被插入到队列中。你无法防止这一点。

你需要做的是记住你已经处理了“点击”事件并忽略了之后到达的任何事件(直到你想允许用户再次点击)。听起来你已经尝试过了。请发布您的代码,以便我们可以看到什么是错的。


看到你的代码后,我有以下输入:

如果mHandler已在主(UI)线程创建的,你有问题你必须代码在这里是做网络I/O和睡眠。你绝对不能在主(UI)线程上做到这一点。确保这些东西在后台线程中运行。为此,请创建您自己的Thread或确保您的Handler是在后台线程上创建的(请参阅HandlerThread作为一个示例)。

在您拨打postDelayed()之前,请将布尔变量running设置为true。当发布的Runnable完成时,该标志应清除为false。为了确保这一点,请将整个run()方法包装在try/catch中,并清除finally块中的变量。

lock()中,首先检查布尔变量running是否为true。如果是这样,你应该立即返回,这会忽略在你没有准备好的时候发生的点击事件。

+0

我已经添加了上述方法之一的代码。 –

+0

布尔型“ok”应该与您提出的'running'具有相同的用途。 –

+0

然后我不明白这个问题。请解释什么是崩溃,你得到什么异常以及哪些不起作用。 –