Skip to content

Streaming

O processDataStream aceita um Stream<Map<String, dynamic>> em vez de uma lista completa. Os registros são consumidos incrementalmente, sem carregar tudo em memória de uma vez.

Uso

dart
final engine = SulfiteEngineImpl();
final report = await engine.parseReport(reportJson);

// Stream de registros (ex: de um banco de dados, API paginada, arquivo grande)
Stream<Map<String, dynamic>> getRecords() async* {
  for (var i = 0; i < 10000; i++) {
    yield {
      'order_id': 'ORD-$i',
      'customer': 'Cliente $i',
      'amount': (i * 10.5),
    };
  }
}

final context = await engine.processDataStream(
  report,
  getRecords(),
  dataSourceId: 'sales',
);

final pdf = await engine.renderToPdf(context);

Assinatura

dart
Future<Map<String, dynamic>> processDataStream(
  ReportDefinition report,
  Stream<Map<String, dynamic>> dataStream, {
  String? dataSourceId,
  bool strict = true,
});
ParâmetroTipoDescrição
reportReportDefinitionDefinição do relatório
dataStreamStream<Map>Stream de registros
dataSourceIdString?ID do data source que recebe os registros
strictboolModo strict (padrão: true)

Quando usar

  • Dados vindos de banco de dados com cursor
  • APIs paginadas
  • Leitura de arquivo grande linha a linha
  • Quando a lista completa não cabe em memória

Isolate

O DataProcessor suporta processamento em Isolate para não bloquear a UI thread:

dart
final processor = DataProcessor(useIsolate: true);

Isso é independente do streaming — pode ser usado com processData ou processDataStream.

Exemplo completo

dart
import 'dart:io';
import 'package:sulfite_core/sulfite_core.dart';

void main() async {
  final engine = SulfiteEngineImpl();

  final report = ReportDefinition(
    reportId: 'stream_demo',
    reportName: 'Stream Demo',
    pageSettings: const PageSettings(
      format: 'A4',
      margins: EdgeInsetsModel(left: 40, right: 40, top: 40, bottom: 40),
    ),
    dataSources: [
      DataSource(
        id: 'sales',
        type: 'list',
        schema: {'order_id': 'string', 'amount': 'number'},
      ),
    ],
    bands: [
      Band.header(id: 'header', height: 60, elements: [
        ReportElement.text(id: 'title', x: 40, y: 20, content: 'Sales Report'),
      ]),
      Band.detail(id: 'detail', dataSourceId: 'sales', height: 25, elements: [
        ReportElement.field(id: 'f1', x: 40, y: 5, width: 100, binding: 'order_id'),
        ReportElement.field(id: 'f2', x: 200, y: 5, width: 100, binding: 'amount', format: 'currency:BRL'),
      ]),
      Band.summary(id: 'summary', height: 40, elements: [
        ReportElement.aggregate(id: 'total', x: 200, y: 10, width: 100, verb: 'SUM', targetKey: 'amount', format: 'currency:BRL'),
      ]),
    ],
  );

  Stream<Map<String, dynamic>> salesStream() async* {
    for (var i = 1; i <= 5000; i++) {
      yield {'order_id': 'ORD-$i', 'amount': i * 12.50};
    }
  }

  final context = await engine.processDataStream(
    report,
    salesStream(),
    dataSourceId: 'sales',
  );

  final pdf = await engine.renderToPdf(context);
  File('stream_output.pdf').writeAsBytesSync(pdf);
}

Sulfite do 🇧🇷 para o mundo © 2026 Rafael S. Pinheiro