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
相关产品推荐
相关产品推荐

