You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter使用smswatcher时StreamBuilder不更新问题求助

Flutter SMS监听问题:StreamBuilder一直处于waiting状态

问题描述

使用smswatcher包监听短信,后台通过flutter_background_service能正常收到短信并打印,但前端的StreamBuilder始终停在connectionState.waiting状态,完全不响应流推送的数据。

相关代码

home_page.dart

import 'package:namer_app/sms_service.dart';
...
StreamBuilder(
  stream: SmsService().getSmsStream(), // 获取收到的短信
  builder: (context, snap) {
    if (snap.connectionState == ConnectionState.waiting) {
      return CircularProgressIndicator(); // 显示加载指示器
    } else if (snap.hasError) {
      return Text('Error: ${snap.error}'); // 处理错误
    } else if (snap.hasData) {
      return ListTile(
        title: Text(snap.data?["sender"] ?? "NA"),
        subtitle: Text(snap.data?["body"] + dateTimeString ?? "NA"),
      );
    } else {
      return Text("No SMS available"); // 处理无数据状态
    }
  }
),

sms_service.dart

// 外部导入包
import 'dart:async';
import 'package:smswatcher/smswatcher.dart';

// SmsService类
class SmsService {
  final smsWatcher = Smswatcher(); // 初始化SmsWatcher
  late StreamSubscription smsSubscription; // 处理短信流

  // 开始监听收到的短信
  Stream<Map<String, dynamic>> getSmsStream() {
    return smsWatcher.getStreamOfSMS().map((sms) {
      return {
        "sender": sms["sender"] ?? "NA",
        "body": sms["body"] ?? "NA",
        "timestamp": sms["timestamp"] ?? DateTime.now().toString(), // 若不存在则添加时间戳
      };
    });
  }
}

background_services.dart

...
@pragma('vm:entry-point')
void onStart(ServiceInstance service) async {
  DartPluginRegistrant.ensureInitialized();

  switch (service.runtimeType) {
    case AndroidServiceInstance: // 处理安卓特定服务
      // 监听短信流
      SmsService().getSmsStream().listen((smsData) async {
        sender = smsData['sender'];
        body = smsData['body'];
        print("$sender $body");
      });
...

问题原因

每次调用SmsService().getSmsStream()都会创建一个全新的SmsService实例,导致:

  • 前端StreamBuilder订阅的是独立的流实例
  • 后台监听的是另一个完全不同的流实例
    两者无关联,后台收到短信时前端流根本没收到数据,一直处于等待状态。

解决方案

1. 将SmsService改为单例模式

确保全局只有一个SmsService实例,让UI和后台共享同一个流:

修改sms_service.dart:

import 'dart:async';
import 'package:smswatcher/smswatcher.dart';

class SmsService {
  // 全局唯一的单例实例
  static final SmsService _instance = SmsService._internal();
  factory SmsService() => _instance;
  SmsService._internal();

  final smsWatcher = Smswatcher();
  late StreamSubscription smsSubscription;

  Stream<Map<String, dynamic>> getSmsStream() {
    return smsWatcher.getStreamOfSMS().map((sms) {
      return {
        "sender": sms["sender"] ?? "NA",
        "body": sms["body"] ?? "NA",
        "timestamp": sms["timestamp"] ?? DateTime.now().toString(),
      };
    });
  }
}

2. 调整前端StreamBuilder的调用方式

在页面中使用同一个单例实例的流,避免每次重建都创建新对象:

修改home_page.dart:

import 'package:namer_app/sms_service.dart';

// 页面内初始化单例实例
final smsService = SmsService();

...

StreamBuilder(
  stream: smsService.getSmsStream(), // 使用全局唯一的流
  builder: (context, snap) {
    if (snap.connectionState == ConnectionState.waiting || !snap.hasData) {
      return Text("暂无短信"); // 替换加载指示器,避免一直转圈
    } else if (snap.hasError) {
      return Text('错误: ${snap.error}');
    } else {
      final dateTimeString = snap.data?["timestamp"] ?? "";
      return ListTile(
        title: Text(snap.data?["sender"] ?? "NA"),
        subtitle: Text('${snap.data?["body"] ?? "NA"} $dateTimeString'),
      );
    }
  }
),

3. 可选:优化流的初始状态

如果不想让StreamBuilder一直显示加载状态,可以给流添加初始数据(需依赖rxdart包):

在sms_service.dart中修改:

// 先添加依赖:dependencies: rxdart: ^0.27.7
import 'package:rxdart/rxdart.dart';

...

Stream<Map<String, dynamic>> getSmsStream() {
  return smsWatcher.getStreamOfSMS()
      .map((sms) => {
        "sender": sms["sender"] ?? "NA",
        "body": sms["body"] ?? "NA",
        "timestamp": sms["timestamp"] ?? DateTime.now().toString(),
      })
      .startWith({"sender": "NA", "body": "暂无短信", "timestamp": ""});
}

这样StreamBuilder一开始就能收到初始数据,不会停在waiting状态。

内容的提问来源于stack exchange,提问作者Kiostz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 07:04:53