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

调用(listAdapter as WiFiPeerListAdapter).notifyDataSetChanged()引发崩溃求助

问题解决:ListFragment中listAdapter空指针导致的崩溃

场景复现

在基于ListFragment的开发中,于onViewCreated方法内初始化适配器:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    listAdapter = WiFiPeerListAdapter(requireContext(), R.layout.row_devices, peers)
}

执行clearPeers方法时触发崩溃:

fun clearPeers() {
    peers.clear()
    (listAdapter as WiFiPeerListAdapter).notifyDataSetChanged()
}

此处listAdapter来自ListFragment的setListAdapter方法:

public void setListAdapter(@Nullable ListAdapter adapter) {
    boolean hadAdapter = mAdapter != null;
    mAdapter = adapter;
    if (mList != null) {
        mList.setAdapter(adapter);
        if (!mListShown && !hadAdapter) {
            // The list was hidden, and previously didn't have an
            // adapter.  It is now time to show it.
            setListShown(true, requireView().getWindowToken() != null);
        }
    }
}

崩溃日志

FATAL EXCEPTION: main
Process: com.tsfapps.wifip2p, PID: 29222
java.lang.RuntimeException: Error receiving broadcast Intent { act=android.net.wifi.p2p.CONNECTION_STATE_CHANGE flg=0x24000010 (has extras) } in com.tsfapps.wifip2p.WiFiDirectBroadcastReceiver@b154cba
at android.app.LoadedApk$ReceiverDispatcher$Args.lambda$getRunnable$0$LoadedApk$ReceiverDispatcher$Args(LoadedApk.java:1689)
at android.app.LoadedApk$ReceiverDispatcher$Args$$ExternalSyntheticLambda0.run(Unknown Source:2)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7839)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
Caused by: java.lang.NullPointerException: null cannot be cast to non-null type com.tsfapps.wifip2p.DeviceListFragment.WiFiPeerListAdapter
at com.tsfapps.wifip2p.DeviceListFragment.clearPeers(DeviceListFragment.kt:102)
at com.tsfapps.wifip2p.MainActivity.resetData(MainActivity.kt:159)
at com.tsfapps.wifip2p.WiFiDirectBroadcastReceiver.onReceive(WiFiDirectBroadcastReceiver.kt:77)
... 11 more

问题原因

  1. 适配器未完成初始化:clearPeers在Fragment的onViewCreated回调执行前被调用(比如广播接收器提前触发),此时listAdapter仍为null,Kotlin非空强转as WiFiPeerListAdapter直接抛出空指针异常。
  2. 适配器未正确绑定:仅给listAdapter赋值但未调用setListAdapter,导致适配器未被Fragment正确持有,视图重建或生命周期异常时可能丢失适配器引用。

解决方案

1. 安全转型避免空指针

修改clearPeers方法,使用as?安全转型,避免空指针崩溃:

fun clearPeers() {
    peers.clear()
    val adapter = listAdapter as? WiFiPeerListAdapter
    adapter?.notifyDataSetChanged()
}

2. 正确绑定适配器到ListView

在onViewCreated中调用setListAdapter,确保适配器被Fragment和ListView持有:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    val adapter = WiFiPeerListAdapter(requireContext(), R.layout.row_devices, peers)
    listAdapter = adapter
    setListAdapter(adapter) // 关键:绑定适配器到ListView
}

3. 合理管理广播接收器生命周期

在Fragment的onStart中注册广播接收器,onStop中注销,确保仅当Fragment处于活跃状态时才触发广播回调,避免提前调用clearPeers:

override fun onStart() {
    super.onStart()
    // 注册WiFi P2P广播接收器
}

override fun onStop() {
    super.onStop()
    // 注销WiFi P2P广播接收器
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 12:06:58