admin管理员组

文章数量:1200973

I am porting an Android Native project written in Java to a flutter, specifically targeting Android, that has to read data from and write data to a physical hardware device, using the USB Serial Port.

There are many places where I want the calls to be synchronous like in my Native project. By synchronous, meaning that the write and read calls should be sequentially executed and that the main UI waits till the response from the device is read successfully and then the execution proceeds.

The libraries which I used for serial communication before (in my native app) had synchronous APIs and I notice that almost all of the dart packages which perform the same task (essentially are wrappers around those libraries) provide asynchronous APIs.

In order to get a synchronous-like behavior, what I am currently doing is to make all the functions that use my basic read and write functions, async and make them return a subtype of Future and then await for completion whenever needed.

For example:- These are some of my basic functions implemented in the class which handles all communication using the asynchronous API provided by the dart package usb_serial -

Future<void> open() async {
    if (!deviceFound) {
      throw Exception("Device not connected");
    }
    mPort = await mDevice!.create();

    bool openResult = await mPort!.open();
    if (!openResult) {
      throw Exception("Failed to open");
    }
    await mPort!.setPortParameters(
      1000000,
      UsbPort.DATABITS_8,
      UsbPort.STOPBITS_1,
      UsbPort.PARITY_NONE,
    );
    mPort!.inputStream!.listen((_) => ());
    connected = true;
  }

  Future<int> read(Uint8List dest, int bytesToRead, int timeoutMillis) async {
    int numBytesRead = 0;
    await for (Uint8List receivedData
        in mPort!.inputStream!.timeout(Duration(milliseconds: timeoutMillis))) {
      dest.setRange(0, receivedData.length, receivedData);
      if (receivedData.length == bytesToRead) {
        print("Read: $bytesToRead");
      } else {
        print("Read Error: ${bytesToRead - numBytesRead}");
      }
      return numBytesRead;
    }
    return numBytesRead;
  }

Now, any function that depends upon read also has to be declared async-

Future<int> _commonRead(int bytesToRead) async {
    final List<int> bytesRead = [0];
    if (_mCommunicationHandler.isConnected()) {
      bytesRead[0] =
          await _mCommunicationHandler.read(_buffer, bytesToRead, _timeout);
    }
    return bytesRead[0];
  }

Many functions which use one such function are declared as async, await for the previous function and return a subtype of Future. This goes on and on in my code till I finally reach the point where I don't have to await for the call, i.e., don't require synchronous communication.

My question is that can't we somehow make these calls synchronous and avoid all that code?

Something like my native API (which uses a synchronous API) -

public int read(byte[] dest, int bytesToBeRead, int timeoutMillis) throws IOException {
        int numBytesRead = 0;
        int readNow;
        Log.v(TAG, "TO read : " + bytesToBeRead);
        int bytesToBeReadTemp = bytesToBeRead;
        while (numBytesRead < bytesToBeRead) {
            readNow = port.read(mReadBuffer, bytesToBeReadTemp, timeoutMillis);
            if (readNow == 0) {
                Log.e(TAG, "Read Error: " + bytesToBeReadTemp);
                return numBytesRead;
            } else {
                System.arraycopy(mReadBuffer, 0, dest, numBytesRead, readNow);
                numBytesRead += readNow;
                bytesToBeReadTemp -= readNow;
            }
        }
        Log.v("Bytes Read", "" + numBytesRead);
        return numBytesRead;
  }

Since the main issue is that the package that I am using provides a asynchronous API only, I tried to write my own dart package that wraps around an Android library (which has synchronous functions), but I am stuck at this point (invokeMethod returns a subtype of Future)-

Future<bool> open() async {
    return await _channel.invokeMethod("open");
  }

Is there any way we can make write a synchronous API in dart for I/O communications?

If possible, would that be recommended or is my approach that uses a combination of Future, async and await better? Coming from a Java background, such an implementation seems complicating.

本文标签: androidSynchronous IO Operations in DartStack Overflow