0

私はToggleButton .on ON および OFF アクションの数を使用しているアプリケーションを開発しています。私は異なるアクションを実行しています。ホームオートメーションベースのアプリケーションなので、ボタンはAC、TV、ライトなど用です。この機器のオンとオフにバイト配列を固定しています。ソケットを使用してこのバイト配列を読み書きしています。しかし、私の問題は、ユーザーが2つのボタンを同時に押すと、ボタンのステータスが点滅し、ANR ダイアログが表示されることがあります。

ここに私のコードスニペットがあります:

@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() メソッドです。

private synchronized void setByteArray(final byte a, final byte b) 
    {
        new Thread (new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                try {

                    byte[] data2 = new byte[1024], packet2 =
                        { 
                            (byte) 0x00,(byte) 0x00,(byte) 0x00,
                            (byte) 0x00,(byte) 0x00,(byte) 0x06,
                            (byte) 0x01,(byte) 0x05,(byte) 0x00, 
                             a, b,(byte) 0x00 
                        };

                    //o.write(packet2);
                     write(packet2);
                    i.read(data2, 0, 1024);
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }).start(); 
    }

アップデート:

ここに write() メソッドがあります

public synchronized  void write(byte[] pkg)
{
       try {
            o.write(pkg);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
     }

初期化:

s = new Socket(ip, Integer.parseInt(port));
i = s.getInputStream();
o = s.getOutputStream();

Update2 これは、ステータスを設定するためにメインスレッドで行っていることです

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();
        }

    }
}

updateButtons()

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); 
        }

    }
};

この状況に対処する方法。私はこの種のトグルボタンを24個持っています。誰かが以前にこの問題を抱えていたら、私と共有してください。

任意のヘルプとアイデアをいただければ幸いです。
ありがとう

4

2 に答える 2

1

シングルスレッドエグゼキュータを使用して、データを順番に送信します。データ転送ごとに新しいスレッドを作成しないでください。

Executor executor = Executors.newSingleThreadExecutor();

private void setByteArray(final byte a, final byte b) {
    executor.execute(new Runnable() { 
        public void run() { 
            // your code here
        } 
    });
}

すべてのRunnableは1つずつ実行されます。

于 2013-02-06T12:46:02.603 に答える
0

あなたが何をしようとしているのかを少し理解した上で、次のことをお勧めします。

  • アクティビティに値の完全な配列を用意します。
  • クリック イベント ハンドラーで値の配列を変更し、
  • その後、そのAsyncTask場で新しく作成されたものを開始します。
  • そのonPreExecuteAsyncTask (メイン UI スレッドで実行される) で、すべてのチェックボックスを無効にします。
  • AsyncTaskdoInBackgroundの中で、値を送信し、再度受信します。
  • onPostExecute、新しく受信したデータに従ってすべてのチェックボックスの状態を設定し、後で有効にします。

これが十分に反応しない場合は、設定の競合を処理する方法を決定する必要があります。これは設定の性質によると思います。いずれにせよ、スキームは簡単に拡張できます。

  • onPreExecute、現在の値のコピーを作成しますが、チェックボックスを無効にしないでください。
  • doInBackground、配列の別のコピーで値を受け取ります。
  • (onPostExecuteメイン UI スレッドで実行される) で、受信した値をチェックボックスの値と比較します。それらが等しくない場合は、新しい AsyncTask を起動して、ユーザー設定を表す値を送信します。

これは、ユーザーの設定がフィードバックを上書きすることになっていることを意味する、競合解決のための戦略を実装します。別の戦略が必要な場合は、それを実装する方法がわかります。

于 2013-02-06T14:19:58.943 に答える