Вызов функции в потоке Android, который уже запущен? Написать на той же ветке, что слушает по Bluetooth? - PullRequest
0 голосов
/ 11 января 2019

Следующая проблема касается чтения и записи в том же потоке, который используется для обработки разъема Bluetooth в Android.

Я не понимаю, как можно вызвать функцию записи в потоке, который уже запущен. Код работает отлично, но я не могу понять, почему.

В следующем коде с сайта android dev поток, кажется, продолжает слушать бесконечный цикл. Кроме того, функция socket.getInputStream() является блокирующим вызовом, означающим, что она ожидает, пока не найдутся данные для чтения, прежде чем эта строка будет выполнена. Тогда я не понимаю, как при вызове функции ConnectedThread.write() эта функция вызывается мгновенно. Если поток уже занят прослушиванием входящих данных, как он может write()? Разве он не должен завершить функцию run(), прежде чем сможет write()? И как написан код, не похоже, что функция run() когда-либо завершит выполнение, потому что находится в бесконечном цикле.

// Code
public class MyBluetoothService {
    private static final String TAG = "MY_APP_DEBUG_TAG";
    private Handler mHandler; // handler that gets info from Bluetooth service

    // Defines several constants used when transmitting messages between the
    // service and the UI.
    private interface MessageConstants {
        public static final int MESSAGE_READ = 0;
        public static final int MESSAGE_WRITE = 1;
        public static final int MESSAGE_TOAST = 2;

        // ... (Add other message types here as needed.)
    }

    private class ConnectedThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final InputStream mmInStream;
        private final OutputStream mmOutStream;
        private byte[] mmBuffer; // mmBuffer store for the stream

        public ConnectedThread(BluetoothSocket socket) {
            mmSocket = socket;
            InputStream tmpIn = null;
            OutputStream tmpOut = null;

            // Get the input and output streams; using temp objects because
            // member streams are final.
            try {
                tmpIn = socket.getInputStream();
            } catch (IOException e) {
                Log.e(TAG, "Error occurred when creating input stream", e);
            }
            try {
                tmpOut = socket.getOutputStream();
            } catch (IOException e) {
                Log.e(TAG, "Error occurred when creating output stream", e);
            }

            mmInStream = tmpIn;
            mmOutStream = tmpOut;
        }

        public void run() {
            mmBuffer = new byte[1024];
            int numBytes; // bytes returned from read()

            // Keep listening to the InputStream until an exception occurs.
            while (true) {
                try {
                    // Read from the InputStream.
                    numBytes = mmInStream.read(mmBuffer);
                    // Send the obtained bytes to the UI activity.
                    Message readMsg = mHandler.obtainMessage(
                            MessageConstants.MESSAGE_READ, numBytes, -1,
                            mmBuffer);
                    readMsg.sendToTarget();
                } catch (IOException e) {
                    Log.d(TAG, "Input stream was disconnected", e);
                    break;
                }
            }
        }

        // Call this from the main activity to send data to the remote device.
        public void write(byte[] bytes) {
            try {
                mmOutStream.write(bytes);

                // Share the sent message with the UI activity.
                Message writtenMsg = mHandler.obtainMessage(
                        MessageConstants.MESSAGE_WRITE, -1, -1, mmBuffer);
                writtenMsg.sendToTarget();
            } catch (IOException e) {
                Log.e(TAG, "Error occurred when sending data", e);

                // Send a failure message back to the activity.
                Message writeErrorMsg =
                        mHandler.obtainMessage(MessageConstants.MESSAGE_TOAST);
                Bundle bundle = new Bundle();
                bundle.putString("toast",
                        "Couldn't send data to the other device");
                writeErrorMsg.setData(bundle);
                mHandler.sendMessage(writeErrorMsg);
            }
        }

        // Call this method from the main activity to shut down the connection.
        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "Could not close the connect socket", e);
            }
        }
    }
}

Код работает, как и ожидалось, но я не понимаю, почему.

Ответы [ 2 ]

0 голосов
/ 11 января 2019

Я не понимаю, как можно вызвать функцию записи в потоке, который уже запущен ...

Вы не "вызываете это в потоке ." Вы звоните по номеру Thread. Thread - это объект в вашей программе с методами, которые ваш код может вызывать точно так же, как он вызывает методы любого другого объекта. Класс Thread имеет один особый метод экземпляра, t.start(), который создает новую операционную систему thread , но в остальном он такой же, как и любой другой класс Java.

Метод t.start() создает новый поток . Новый поток вызывает метод run() вашего Thread объекта, а затем после того, как run() вернет или сгенерирует исключение, новый поток умрет.

Вы не показали нам другой код, который вызывает write(), но, вероятно, он просто сказал @nandsito: какой-то другой поток в вашем коде вызывает этот метод для вашего Thread экземпляра.

0 голосов
/ 11 января 2019

Кажется, есть некоторая путаница вокруг некоторых понятий. Я постараюсь сделать некоторые разъяснения.

функция socket.getInputStream () является блокирующим вызовом

Это просто добытчик, он не блокирует. socket.getInputStream().read() является блокирующим.

Тогда я не понимаю, как при вызове функции ConnectedThread.write () эта функция вызывается мгновенно.

write(), вероятно, вызывается другим потоком. В этом случае думайте о ConnectedThread как об общем объекте, как о любом другом.

EDIT

Вот пример кода, который иллюстрирует новый поток, работающий вместе с уже существующим потоком.

// At this point you have one thread (there may be more,
// but suppose it's only one).
// The thread is executing the code below.

ConnectedThread connectedThread = new ConnectedThread(socket);
connectedThread.start();

// Now you have two threads running simultaneously.
// The new thread is doing whatever the run() method defined in
// ConnectedThread,
// that is that infinite loop with read() calls.
// But this thread goes on.

connectedThread.write();

// The write() call above is executed in this thread,
// which has nothing to do with
// the run() defined in ConnectedThread.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...