首页 > 代码库 > Android之Handler用法总结[一]

Android之Handler用法总结[一]

以谷歌自带的Bluetooth Chat举例说明,例子中有三个源文件,分别为:BluetoothChat.java, DeviceListActivity.java, BluetoothChatService.java。

其中BluetoothChat.java是主UI的Activity,DeviceListActivity.java是配对设备列表选择UI的Activity,BluetoothChatService.java是功能类内含多个

线程的定义。

1. 主UI中定义Handler成员变量mHandler:

  // The Handler that gets information back from the BluetoothChatService  private final Handler mHandler = new Handler() {        @Override        public void handleMessage(Message msg) {            switch (msg.what) {            case MESSAGE_STATE_CHANGE:                if(D) Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1);                switch (msg.arg1) {                case BluetoothChatService.STATE_CONNECTED:                    setStatus(getString(R.string.title_connected_to, mConnectedDeviceName));                    mConversationArrayAdapter.clear();                    break;                case BluetoothChatService.STATE_CONNECTING:                    setStatus(R.string.title_connecting);                    break;                case BluetoothChatService.STATE_LISTEN:                case BluetoothChatService.STATE_NONE:                    setStatus(R.string.title_not_connected);                    break;                }                break;            case MESSAGE_WRITE:                byte[] writeBuf = (byte[]) msg.obj;                // construct a string from the buffer                String writeMessage = new String(writeBuf);                mConversationArrayAdapter.add("Me:  " + writeMessage);                break;            case MESSAGE_READ:                byte[] readBuf = (byte[]) msg.obj;                // construct a string from the valid bytes in the buffer                String readMessage = new String(readBuf, 0, msg.arg1);                mConversationArrayAdapter.add(mConnectedDeviceName+":  " + readMessage);                break;            case MESSAGE_DEVICE_NAME:                // save the connected device‘s name                mConnectedDeviceName = msg.getData().getString(DEVICE_NAME);                Toast.makeText(getApplicationContext(), "Connected to "                               + mConnectedDeviceName, Toast.LENGTH_SHORT).show();                break;            case MESSAGE_TOAST:                Toast.makeText(getApplicationContext(), msg.getData().getString(TOAST),                               Toast.LENGTH_SHORT).show();                break;            }        }    };

2. 主UI中初始化BluetoothChatService的实例,并在初始化时将mHandler作参数传递给实例:

  private void setupChat() {        Log.d(TAG, "setupChat()");        // Initialize the array adapter for the conversation thread        mConversationArrayAdapter = new ArrayAdapter<String>(this, R.layout.message);        mConversationView = (ListView) findViewById(R.id.in);        mConversationView.setAdapter(mConversationArrayAdapter);        // Initialize the compose field with a listener for the return key        mOutEditText = (EditText) findViewById(R.id.edit_text_out);        mOutEditText.setOnEditorActionListener(mWriteListener);        // Initialize the send button with a listener that for click events        mSendButton = (Button) findViewById(R.id.button_send);        mSendButton.setOnClickListener(new OnClickListener() {            public void onClick(View v) {                // Send a message using content of the edit text widget                TextView view = (TextView) findViewById(R.id.edit_text_out);                String message = view.getText().toString();                sendMessage(message);            }        });        // Initialize the BluetoothChatService to perform bluetooth connections        mChatService = new BluetoothChatService(this, mHandler);        // Initialize the buffer for outgoing messages        mOutStringBuffer = new StringBuffer("");    }

3. 主UI中定义事件响应函数(发送按钮),其中调用sendMessage函数:

// Initialize the send button with a listener that for click eventsmSendButton = (Button) findViewById(R.id.button_send);mSendButton.setOnClickListener(new OnClickListener() {  public void onClick(View v) {    // Send a message using content of the edit text widget    TextView view = (TextView) findViewById(R.id.edit_text_out);    String message = view.getText().toString();    sendMessage(message);  }});

4. sendMessage函数中,调用功能类BluetoothChatService.java的子函数:

  /**     * Sends a message.     * @param message  A string of text to send.     */    private void sendMessage(String message) {        // Check that we‘re actually connected before trying anything        if (mChatService.getState() != BluetoothChatService.STATE_CONNECTED) {            Toast.makeText(this, R.string.not_connected, Toast.LENGTH_SHORT).show();            return;        }        // Check that there‘s actually something to send        if (message.length() > 0) {            // Get the message bytes and tell the BluetoothChatService to write            byte[] send = message.getBytes();            mChatService.write(send);            // Reset out string buffer to zero and clear the edit text field            mOutStringBuffer.setLength(0);            mOutEditText.setText(mOutStringBuffer);        }    }

注意这里的mChatSercice.write(send)函数,出于线程安全的考虑,在BluetoothChatService.java中是这么定义的:

  /**     * Write to the ConnectedThread in an unsynchronized manner     * @param out The bytes to write     * @see ConnectedThread#write(byte[])     */    public void write(byte[] out) {        // Create temporary object        ConnectedThread r;        // Synchronize a copy of the ConnectedThread        synchronized (this) {            if (mState != STATE_CONNECTED) return;            r = mConnectedThread;        }        // Perform the write unsynchronized        r.write(out);    }

这里定义了一个临时线程类ConnectedThread r,而这个线程类的定义如下:

    /**     * This thread runs during a connection with a remote device.     * It handles all incoming and outgoing transmissions.     */    private class ConnectedThread extends Thread {        private final BluetoothSocket mmSocket;        private final InputStream mmInStream;        private final OutputStream mmOutStream;        public ConnectedThread(BluetoothSocket socket, String socketType) {            Log.d(TAG, "create ConnectedThread: " + socketType);            mmSocket = socket;            InputStream tmpIn = null;            OutputStream tmpOut = null;            // Get the BluetoothSocket input and output streams            try {                tmpIn = socket.getInputStream();                tmpOut = socket.getOutputStream();            } catch (IOException e) {                Log.e(TAG, "temp sockets not created", e);            }            mmInStream = tmpIn;            mmOutStream = tmpOut;        }        public void run() {            Log.i(TAG, "BEGIN mConnectedThread");            byte[] buffer = new byte[1024];            int bytes;            // Keep listening to the InputStream while connected            while (true) {                try {                    // Read from the InputStream                    bytes = mmInStream.read(buffer);                    // Send the obtained bytes to the UI Activity                    mHandler.obtainMessage(BluetoothChat.MESSAGE_READ, bytes, -1, buffer)                            .sendToTarget();                } catch (IOException e) {                    Log.e(TAG, "disconnected", e);                    connectionLost();                    // Start the service over to restart listening mode                    BluetoothChatService.this.start();                    break;                }            }        }        /**         * Write to the connected OutStream.         * @param buffer  The bytes to write         */        public void write(byte[] buffer) {            try {                mmOutStream.write(buffer);                // Share the sent message back to the UI Activity                mHandler.obtainMessage(BluetoothChat.MESSAGE_WRITE, -1, -1, buffer).sendToTarget();            } catch (IOException e) {                Log.e(TAG, "Exception during write", e);            }        }        public void cancel() {            try {                mmSocket.close();            } catch (IOException e) {                Log.e(TAG, "close() of connect socket failed", e);            }        }    }

 从write()函数的定义中可以看到,mHandler.obtainMessage(BluetoothChat.MESSAGE_WRITE, -1, -1, buffer) .sendToTarget()实现了线程和主UI之间的通信。

Android之Handler用法总结[一]