Home > Mobile >  Flutter: Cannot retrieve data from a Future function on FutureBuilder
Flutter: Cannot retrieve data from a Future function on FutureBuilder

Time:06-01

I'm building a receipt scanner using the Flutter OCR plugin provided by Veryfi.
Here's a Stream function that reads an image and returns a dynamic array containing the necessary values.
Note the credentials from VeryfiDart are removed.
The showImage variable is an image file either captured from a camera or selected from an image gallery.

class ReceiptProcessor {
  Future<dynamic> processReceipt(File image) async {
    List<List<Widget>> itemList = [];

    Uint8List imageData = image.readAsBytesSync();
    String fileData = base64Encode(imageData);
    VeryfiDart client = VeryfiDart(
      'ClientId',
      'ClientSecret',
      'Username',
      'ApiKey',
    );

    await client.processDocument('receipt.jpg', fileData).then(
      (response) {
        String totalPayment = response['total'].toString();
        String currencyCode = response['currency_code'];
        String vendorName = response['vendor']['name'];

        for (var item in response['line_items']) {
          String description = item['description'];
          String quantity = item['quantity'].toString();
          String totalCost = item['total'].toString();

          List<Widget> itemInfo = [
            Text(description),
            Text(quantity),
            Text(totalCost)
          ];
          itemList.add(itemInfo);
        }

        List<dynamic> processedDetails = [
          Text(totalPayment),
          Text(currencyCode),
          Text(vendorName),
          itemList
        ];

        return processedDetails;
      },
    ).catchError((error) {
      return Text('Error');
    });
  }
}

Apparently the data are properly fetched, but issues occur when trying to retrieve the data and display it.

class ReceiptDetailsView extends StatefulWidget {
  const ReceiptDetailsView({Key? key}) : super(key: key);

  @override
  State<ReceiptDetailsView> createState() => _ReceiptDetailsViewState();
}

class _ReceiptDetailsViewState extends State<ReceiptDetailsView> {
  Future<dynamic> loadProcessedReceipt() async {
    ReceiptProcessor rp = ReceiptProcessor();
    return await rp.processReceipt(showImage!);
  }

  late Future<dynamic> processedReceipt;

  @override
  void initState() {
    super.initState();
    processedReceipt = loadProcessedReceipt();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.all(10.0),
      child: FutureBuilder<dynamic>(
        future: processedReceipt,
        builder: (context, snapshot) {
          switch (snapshot.connectionState) {
            case ConnectionState.waiting:
              return CircularProgressIndicator();
            case ConnectionState.done:
              if (snapshot.hasError) {
                return Text('Error: ${snapshot.error}');
              } else if (snapshot.data != null) {
                return Text('Success');
              }
          }
          return Text('Error');
        },
      ),
    );
  }
}

I used a FutureBuilder here, but continuously an empty snapshot containing a null data is returned; thus, 'Error' is displayed on the view.
Any suggestions would be appreciated. A 'Success' Text should appear when the snapshot data is properly retrieved.

CodePudding user response:

I think your function does indeed not return anything. Mostly, because your use of the then function. Since you return inside your then callback, the value is not returned globally but instead just for this function.

There's two options, you could either return the value that you resolve in the then callback like this:

return await client.processDocument(..).then(...);

Or don't use then at all, and instead keep relying on await:

Map<String, dynamic> response = await client.processDocument(...);
...
return processedDetails;

I would recommend the latter case, where the single return simply returns from the function itself, and you don't include some code in a nested callback function.

  • Related