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

Flutter集成pusher_channels_flutter连接成功后崩溃,报空指针异常

Flutter中使用pusher_channels_flutter: ^2.1.0连接成功后崩溃的问题

我在Flutter应用中使用pusher_channels_flutter: ^2.1.0,该包在旧项目中运行正常,但新项目里Pusher连接成功后应用直接崩溃。尝试将新项目的SDK版本从">=2.18.1 <3.0.0"改为旧项目的sdk: ">=2.16.2 <3.0.0",问题依旧。

错误日志

[+1133 ms] I/flutter ( 6520): Connection: CONNECTED
[+2916 ms] E/AndroidRuntime( 6520): FATAL EXCEPTION: pusher-java-client eventQueue
[        ] E/AndroidRuntime( 6520): Process: com.exptradies.business, PID: 6520
[        ] E/AndroidRuntime( 6520): java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.pusher.client.channel.impl.message.AuthResponse.getChannelData()' on a null object reference
[        ] E/AndroidRuntime( 6520):     at com.pusher.client.channel.impl.PrivateChannelImpl.authorize(PrivateChannelImpl.java:84)
[        ] E/AndroidRuntime( 6520):     at com.pusher.client.channel.impl.PrivateChannelImpl.toSubscribeMessage(PrivateChannelImpl.java:101)
[        ] E/AndroidRuntime( 6520):     at com.pusher.client.channel.impl.ChannelManager.lambda$sendOrQueueSubscribeMessage$0$com-pusher-client-channel-impl-ChannelManager(ChannelManager.java:134)
[   +1 ms] E/AndroidRuntime( 6520):     at com.pusher.client.channel.impl.ChannelManager$$ExternalSyntheticLambda0.run(Unknown Source:4)
[        ] E/AndroidRuntime( 6520):     at com.pusher.client.util.Factory.lambda$queueOnEventThread$0(Factory.java:140)
[        ] E/AndroidRuntime( 6520):     at com.pusher.client.util.Factory$$ExternalSyntheticLambda0.run(Unknown Source:2)
[        ] E/AndroidRuntime( 6520):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
[        ] E/AndroidRuntime( 6520):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
[        ] E/AndroidRuntime( 6520):     at java.lang.Thread.run(Thread.java:923)
[ +170 ms] I/ViewRootImpl@3b6c2d[MainActivity]( 6520): MSG_WINDOW_FOCUS_CHANGED 0 1
[  +15 ms] I/Process ( 6520): Sending signal. PID: 6520 SIG: 9
[ +251 ms] Service protocol connection closed.
[        ] Lost connection to device.

环境信息

Flutter版本

amu@amu-Inspiron-7570:~/Desktop/projects/apps/exptradies/business$ flutter --version
Flutter 3.3.10 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 135454af32 (2 months ago) • 2022-12-15 07:36:55 -0800
Engine • revision 3316dd8728
Tools • Dart 2.18.6 • DevTools 2.15.0

Flutter Doctor结果

amu@amu-Inspiron-7570:~/Desktop/projects/apps/exptradies/business$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.3.10, on Ubuntu 20.04.5 LTS 5.15.0-60-generic, locale en_US.UTF-8)
Checking Android licenses is taking an unexpectedly long time...[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
[✓] Chrome - develop for the web
[✗] Linux toolchain - develop for Linux desktop
    ✗ clang++ is required for Linux development.
      It is likely available from your distribution (e.g.: apt install clang), or can be downloaded from https://releases.llvm.org/
    ✗ ninja is required for Linux development.
      It is likely available from your distribution (e.g.: apt install ninja-build), or can be downloaded from https://github.com/ninja-build/ninja/releases
    ✗ GTK 3.0 development libraries are required for Linux development.
      It is likely available from your distribution (e.g.: apt install libgtk-3-dev)
[✓] Android Studio
[✓] VS Code
[✓] Connected device (3 available)
[✓] HTTP Host Availability

! Doctor found issues in 1 category.

Pusher实现代码

class _NotificationBellState extends State<NotificationBell> {
  var _pusher;
  User? _user;
  
  @override
  void initState() {
    super.initState();
    _get(context);
    _initPusher();
  }

  @override
  void dispose() {
    _pusher.disconnect();
    _pusher.unsubscribe(channelName: "private-notification.${_user!.id}");
    super.dispose();
  }

  Future<void> _initPusher() async {
    _user = Provider.of<ProfileProvider>(context, listen: false).employee!.user;
    _pusher = PusherChannelsFlutter.getInstance();
    try {
      await _pusher.init(
        apiKey: pusherKey,
        cluster: "mt1",
        onConnectionStateChange: onConnectionStateChange,
        onError: onError,
        onSubscriptionSucceeded: onSubscriptionSucceeded,
        onEvent: onEvent,
        onSubscriptionError: onSubscriptionError,
        onDecryptionFailure: onDecryptionFailure,
        onMemberAdded: onMemberAdded,
        onMemberRemoved: onMemberRemoved,
        //authEndpoint: "https://my-website.com/broadcasting/auth",
        onAuthorizer: onAuthorizer,
      );
      await _pusher.subscribe(channelName: "private-notification.${_user!.id}");
      await _pusher.connect();
    } catch (e) {
      print("error in initialization: $e");
    }
  }

  dynamic onAuthorizer(
      String channelName, String socketId, dynamic options) async {
    String token = await Store.read("token");
    var authUrl = "$baseUrl/broadcasting/auth";
    var result = await http.post(
      Uri.parse(authUrl),
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Authorization': 'Bearer $token',
      },
      body: 'socket_id=$socketId&channel_name=$channelName',
    );
    var json = jsonDecode(result.body);
    return json;
  }

  void onError(String message, int? code, dynamic e) {
    print("onError: $message code: $code exception: $e");
  }

  void onConnectionStateChange(dynamic currentState, dynamic previousState) {
    print("Connection: $currentState");
  }

  void onMemberRemoved(String channelName, PusherMember member) {
    print("onMemberRemoved: $channelName member: $member");
  }

  void onMemberAdded(String channelName, PusherMember member) {
    print("onMemberAdded: $channelName member: $member");
  }

  void onSubscriptionSucceeded(String channelName, dynamic data) {
    print("onSubscriptionSucceeded: $channelName data: $data");
  }

  void onSubscriptionError(String message, dynamic e) {
    print("onSubscriptionError: $message Exception: $e");
  }

  void onEvent(PusherEvent event) {
    print("onEvent: $event");
    if (event.eventName == 'notification-event') {
      FlutterRingtonePlayer.playNotification();
      Provider.of<NotificationProvider>(context, listen: false)
          .setNotificationCount(1);
    }
  }

  void onDecryptionFailure(String event, String reason) {
    print("onDecryptionFailure: $event reason: $reason");
  }
}

可能的解决方案

  • 检查授权接口返回值:错误日志显示授权响应为null,需在onAuthorizer中打印result.statusCode和result.body,确认后端是否返回包含auth(私有频道可能还需channel_data)的合法JSON数据。若后端返回错误或空数据,会直接导致客户端崩溃。
  • 调整初始化顺序:将先订阅频道再连接的逻辑改为先连接成功后再订阅:
    await _pusher.connect();
    await _pusher.subscribe(channelName: "private-notification.${_user!.id}");
    
  • 处理空值安全:在_initPusher中先判断_user是否为空,避免后续使用_user!触发空指针异常。
  • 捕获授权过程异常:在onAuthorizer中添加异常捕获,确保请求失败时不会返回null,而是触发onSubscriptionError:
    dynamic onAuthorizer(
        String channelName, String socketId, dynamic options) async {
      try {
        String token = await Store.read("token");
        var authUrl = "$baseUrl/broadcasting/auth";
        var result = await http.post(
          Uri.parse(authUrl),
          headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
            'Authorization': 'Bearer $token',
          },
          body: 'socket_id=$socketId&channel_name=$channelName',
        );
        if (result.statusCode == 200) {
          return jsonDecode(result.body);
        } else {
          print("Auth request failed with status: ${result.statusCode}, body: ${result.body}");
          return null;
        }
      } catch (e) {
        print("Auth request exception: $e");
        return null;
      }
    }
    
  • 升级包版本:尝试将pusher_channels_flutter升级到最新稳定版,查看是否已修复该空指针问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 20:09:26