Java Android:如何避免在切换按钮上同时执行操作
我正在开发一个应用程序,在这个应用程序中,我使用的是数字。打开和关闭操作,我执行的是不同的操作。它的家庭自动化应用程序,所以按钮是为交流,电视,灯等。我有固定的字节数组来打开和关闭这个设备。我正在使用套接字写入和读取这个字节数组。但我的问题是,当用户同时按下两个按钮时,按钮状态会闪烁,有时会显示ANR对话 以下是我的代码片段:Java Android:如何避免在切换按钮上同时执行操作,java,android,sockets,Java,Android,Sockets,我正在开发一个应用程序,在这个应用程序中,我使用的是数字。打开和关闭操作,我执行的是不同的操作。它的家庭自动化应用程序,所以按钮是为交流,电视,灯等。我有固定的字节数组来打开和关闭这个设备。我正在使用套接字写入和读取这个字节数组。但我的问题是,当用户同时按下两个按钮时,按钮状态会闪烁,有时会显示ANR对话 以下是我的代码片段: @Override public void onClick(View v) { if(v.equals(fanDimmer1)) { i
@Override
public void onClick(View v)
{
if(v.equals(fanDimmer1))
{
if (fanDimmer1.isChecked()) {
setByteArray((byte) 0x01, (byte) 0xff);
} else {
setByteArray((byte) 0x01, (byte) 0x00);
}
}
else if(v.equals(fanDimmer2))
{
if (fanDimmer2.isChecked()) {
setByteArray((byte) 0x02, (byte) 0xff);
} else {
setByteArray((byte) 0x02, (byte) 0x00);
}
}
}
下面是SetByteArray()方法
更新:
下面是write()方法
初始化:
s = new Socket(ip, Integer.parseInt(port));
i = s.getInputStream();
o = s.getOutputStream();
更新2
这就是我在主线程中设置状态所做的
Runnable m_statusChecker = new Runnable()
{
@Override
public void run()
{
if (count == 0) {
updateStatus();
count = 1;
} else {
updateStatus1();
count = 0;
}
m_handler.postDelayed(m_statusChecker,Integer.parseInt(interval));
}
private synchronized void updateStatus()
{
// TODO Auto-generated method stub
try {
byte[] data1 = new byte[1024], packet1 =
{
(byte) 0x00,(byte) 0x00,(byte) 0x00,
(byte) 0x00,(byte) 0x00,(byte) 0x06,
(byte) 0x01,(byte) 0x01,(byte) 0x00,
(byte) 0x00,(byte) 0x00,(byte) 0x19
};
write(packet1);
i.read(data1, 0, 1024);
byte_to_hex = ConversionMethods.bytesToHex(data1).substring(18, 26);
char[] arr = byte_to_hex.toCharArray();
for (int i = 0; i < arr.length - 1; i += 2)
{
char temp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = temp;
}
swapped_result=new String(arr);
result = ConversionMethods.hexStringToNBitBinary(swapped_result, 32);
int counter = 0;
for( int i=0; i<result.length(); i++ )
{
if( result.charAt(i) == '1' )
{
counter++;
}
}
status=Integer.toString(counter);
runOnUiThread(updateButtons);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Runnable m_statusChecker=new Runnable()
{
@凌驾
公开募捐
{
如果(计数=0){
更新状态();
计数=1;
}否则{
updateStatus1();
计数=0;
}
m_handler.postDelayed(m_statusChecker,Integer.parseInt(interval));
}
私有同步的void updateStatus()
{
//TODO自动生成的方法存根
试一试{
字节[]数据1=新字节[1024],数据包1=
{
(字节)0x00,(字节)0x00,(字节)0x00,
(字节)0x00,(字节)0x00,(字节)0x06,
(字节)0x01,(字节)0x01,(字节)0x00,
(字节)0x00,(字节)0x00,(字节)0x19
};
编写(packet1);
i、 读取(数据1,0,1024);
byte_to_hex=ConversionMethods.bytesToHex(data1).substring(18,26);
char[]arr=byte_to_hex.tocharray();
对于(int i=0;i 对于(int i=0;i使用单线程执行器按顺序发送数据。不要为每次数据传输创建新线程
Executor executor = Executors.newSingleThreadExecutor();
private void setByteArray(final byte a, final byte b) {
executor.execute(new Runnable() {
public void run() {
// your code here
}
});
}
所有Runnable都将一个接一个地执行。了解您打算做什么后,我建议如下
- 在你们的活动中有一个完整的值数组
- 使单击事件处理程序修改值数组和
- 之后,启动一个新的动态创建的
AsyncTask
- 在该异步任务(在主UI线程上执行)的
onPreExecute
中,禁用所有复选框
- 在异步任务的
doInBackground
中,发送值并再次接收
- 在
onPostExecute
中,根据新接收的数据设置所有复选框的状态,然后启用它们
如果响应不够,您需要决定如何处理设置冲突。我认为这取决于设置的性质。无论哪种方式,方案都可以轻松扩展:
- 在
onPreExecute
中,复制当前值,但不要禁用复选框
- 在
doInBackground
中,接收数组另一个副本中的值
- 在
onPostExecute
(在主UI线程上执行)中,将收到的Vlaue与复选框的值进行比较。如果它们不相等,则启动新的AsyncTask以发送表示用户设置的值
这实现了一种冲突解决策略,这意味着用户的设置应该覆盖反馈。如果需要另一种策略,您可能会知道如何实现它。因此我应该实现我的setByteArray()
使用executor right的方法?更新了答案。如果您的写/读同步工作,这应该会起作用。谢谢,它提高了性能,但问题还没有解决!我可以在使用Runnable设置按钮状态时使用此逻辑吗
?在实现您的想法后,它只会偶尔闪烁,这对我很好。你怎么办你的意思是“闪烁”?切换按钮可以是开的,也可以是的。你是如何得出你需要使用equals()的结论的
用于比较v
?--什么是i
,为什么o
被注释掉?--您是否知道,当用户按下按钮太快时,您可能会并行启动多个线程?data2
发生了什么事?--已同步的没有做我认为您认为它做的事情。 ;)在处理过程中禁用按钮,并在完成后启用。此外,您可以随时取消正在执行的按钮并启动另一个按钮。@ClassStacker我已更新了问题,请检查它们为什么闪烁?以及您在主线程中做了什么导致ANR?我在给定代码中没有看到任何可能导致ANR的内容。为什么您是否创建iD/oD,但直接从i/o读/写?@Leonidos在主线程中,我正在为该切换按钮设置状态为on | off,以防有人切换风扇,那么它也应该在应用程序中显示为off。因此,我每秒检查一次该状态设置状态。感谢您的回答,我将尝试以这种方式实现
Runnable m_statusChecker = new Runnable()
{
@Override
public void run()
{
if (count == 0) {
updateStatus();
count = 1;
} else {
updateStatus1();
count = 0;
}
m_handler.postDelayed(m_statusChecker,Integer.parseInt(interval));
}
private synchronized void updateStatus()
{
// TODO Auto-generated method stub
try {
byte[] data1 = new byte[1024], packet1 =
{
(byte) 0x00,(byte) 0x00,(byte) 0x00,
(byte) 0x00,(byte) 0x00,(byte) 0x06,
(byte) 0x01,(byte) 0x01,(byte) 0x00,
(byte) 0x00,(byte) 0x00,(byte) 0x19
};
write(packet1);
i.read(data1, 0, 1024);
byte_to_hex = ConversionMethods.bytesToHex(data1).substring(18, 26);
char[] arr = byte_to_hex.toCharArray();
for (int i = 0; i < arr.length - 1; i += 2)
{
char temp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = temp;
}
swapped_result=new String(arr);
result = ConversionMethods.hexStringToNBitBinary(swapped_result, 32);
int counter = 0;
for( int i=0; i<result.length(); i++ )
{
if( result.charAt(i) == '1' )
{
counter++;
}
}
status=Integer.toString(counter);
runOnUiThread(updateButtons);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Runnable updateButtons=new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
txt_status.setText(status);
/*Log.v(TAG, "status is ::"+status);*/
char[] c=result.toCharArray();
int count=0;
for (int i=0;i<24;i++)
{
count++;
char j=c[i];
Log.v(TAG, count+"::"+j);
if(count==1)
toggleButton=dimmerLight1;
else if(count==2)
toggleButton=dimmerLight2;
else if(count==3)
toggleButton=dimmerLight3;
else if(count==4)
toggleButton=dimmerLight4;
else if(count==5)
toggleButton=dimmerLight5;
............
............
if(j=='1')
toggleButton.setChecked(true);
else
toggleButton.setChecked(false);
}
}
};
Executor executor = Executors.newSingleThreadExecutor();
private void setByteArray(final byte a, final byte b) {
executor.execute(new Runnable() {
public void run() {
// your code here
}
});
}