我为具有多个按钮的应用程序编写了一个菜单。其中两个按钮触发两种不同的蓝牙方法。问题是,在多次快速按下这些按钮时,应用程序崩溃,因为每种方法都试图管理蓝牙连接(而另一种方法可能会关闭该连接)。我已经尝试在任何方法运行时设置变量'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);
}
答案 0 :(得分:1)
正如您已经使用布尔值尝试的那样,semaphore可以在这里做到这一点。
答案 1 :(得分:1)
由于Android事件系统的工作方式,您无法通过禁用onClick()
中的按钮来解决此问题。当用户按下按钮时,“click”事件将排队到事件队列。如果用户快速连续按下按钮两次(特别是在低端设备上或当UI线程忙时),则会在队列中插入2个“单击”事件。你不能阻止这种情况。
您需要做的是记住您已经处理了“点击”事件并忽略了之后到达的任何事件(直到您希望允许用户再次点击)。听起来你已经尝试过了。请发布您的代码,以便我们查看错误。
看到你的代码后,我有以下输入:
如果在主(UI)线程上创建了mHandler
,则表示您遇到问题您在这里有代码正在进行网络I / O和休眠。你绝对不能在主(UI)线程上这样做。确保这些东西在后台线程中运行。要执行此操作,请创建自己的Thread
或确保在后台线程上创建Handler
(请参阅HandlerThread
作为示例)。
在致电postDelayed()
之前,请将布尔变量running
设置为true
。发布的false
完成后,此标志应清除为Runnable
。要确保这一点,请将整个run()
方法包装在try/catch
中,并在finally
块中清除变量。
在lock()
中,首先检查布尔变量running
是否为true
。如果是,您应该立即返回,这将忽略您尚未准备好的点击事件。
答案 2 :(得分:0)
试试这个:
bluetoothMethod();
bluetoothButton.setEnabled(false);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
bluetoothButton.setEnabled(true);
}
}, duration);
(持续时间以毫秒为单位)