简体   繁体   English

在已经运行的android线程上调用函数? 写在侦听蓝牙的同一线程上?

[英]Calling a function on an android thread that is already running? Write on the same thread that is listening for Bluetooth?

The following problem is about reading and writing on the same thread that is used for handling a bluetooth socket in android. 以下问题是关于在用于处理android中的蓝牙套接字的同一线程上进行读写的问题。

I don't understand how it is possible to call the write function on a thread that is already running. 我不明白如何在已经运行的线程上调用write函数。 The code works perfectly, but I cannot understand why. 该代码工作正常,但我不明白为什么。

In the following code from the android dev website, thread seems to keep listening in an infinite loop. 在android dev网站的以下代码中,线程似乎在无限循环中不断监听。 Furthermore the socket.getInputStream() function is a blocking call meaning that it waits until there is data to read before that line executes. 此外, socket.getInputStream()函数是一个阻塞调用,这意味着它等待该行执行之前要读取的数据。 I don't understand then how, when the ConnectedThread.write() function is called, that the function is called instantly. 我不明白然后如何在调用ConnectedThread.write()函数时立即调用该函数。 If the thread is already busy listening for incoming data, how can it also write() ? 如果线程已经在忙于侦听传入的数据,它又怎么可以write() Shouldn't it complete the run() function before it can write() ? 它不应该在可以write()之前完成run()函数吗? And the way the code is written it doesn't seem like the run() function will ever finish executing because it is in an infinite loop. 而且代码的编写方式似乎并没有执行完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);
            }
        }
    }
}

The code works as expected, but I don't understand why. 该代码按预期工作,但我不明白为什么。

There seems to be a little confusion around some concepts. 一些概念似乎有些混乱。 I'll try to do some clarification. 我会尝试做一些澄清。

the socket.getInputStream() function is a blocking call socket.getInputStream()函数是一个阻塞调用

It's just a getter, it doesn't block. 这只是吸气剂,不会阻塞。 socket.getInputStream().read() is the blocker one. socket.getInputStream().read()是阻止程序之一。

I don't understand then how, when the ConnectedThread.write() function is called, that the function is called instantly. 我不明白然后如何在调用ConnectedThread.write()函数时立即调用该函数。

write() is probably called by another thread. write()可能被另一个线程调用。 In this case, think of ConnectedThread as a common object like any other. 在这种情况下, ConnectedThread视为一个与其他对象一样的公共对象。

EDIT 编辑

Here's a code example that illustrates the new thread running alongside the thread already present. 这是一个代码示例,它说明新线程与已经存在的线程一起运行。

// 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.

I don't understand how it is possible to call the write function on a thread that is already running... 我不明白如何在已经运行的线程上调用write函数...

You aren't "calling it on a thread ." 您不是在线程上调用它。 You are calling it on a Thread . 您正在Thread上调用它。 A Thread is an object in your program with methods that your code can call in exactly the same way that it calls the methods of any other object. Thread是程序中的一个对象,具有与代码调用任何其他对象的方法完全相同的方法。 The Thread class has one very special instance method, t.start() which creates a new operating system thread , but otherwise, it's just like any other Java class. Thread类有一个非常特殊的实例方法t.start() ,它创建一个新的操作系统线程 ,但除此之外,它与任何其他Java类一样。

The t.start() method creates a new thread . t.start()方法创建一个新线程 The new thread calls your Thread object's run() method, and then after run() returns or throws an exception, the new thread dies. 新线程调用您的Thread对象的run()方法,然后run()返回或引发异常后,新线程死亡。

You haven't showed us the other code that calls write() , but it's probably just as @nandsito said: Some other thread in your code is calling that method on your Thread instance. 您没有向我们展示调用write()的其他代码,但这可能就像@nandsito所说的那样:代码中的其他线程正在Thread实例上调用该方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM