求助:WiFi扫描结果存入ArrayList时异步返回空列表问题
嘿,我完全懂你碰到的这个坑——WiFi扫描是异步操作,你的方法在广播接收器拿到扫描结果之前就已经返回了,所以才会出现onReceive里能打印出数据,但返回的ArrayList却空无一物的情况。
问题根源拆解
调用wifiManager.startScan()后,系统并不会立刻返回扫描结果,而是会在扫描完成后通过WifiManager.SCAN_RESULTS_AVAILABLE_ACTION这个广播来通知你。如果你的方法是同步返回ArrayList,那肯定会“抢跑”——广播还没触发,列表自然是空的。
解决方案:用回调/观察者模式等待结果
最靠谱的方式是放弃“直接返回ArrayList”的思路,改用回调接口或者LiveData来接收异步返回的扫描结果。这里给你举个回调的实现例子:
1. 定义一个扫描结果回调接口
interface WifiScanCallback { fun onScanSuccess(results: ArrayList<ScanResult>) fun onScanFailed() }
2. 重构扫描方法,传入回调
fun scanWifi(context: Context, callback: WifiScanCallback) { val wifiManager = context.getSystemService(Context.WIFI_SERVICE) as WifiManager val scanFilter = IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION) // 创建临时广播接收器 val scanReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { if (intent?.action == WifiManager.SCAN_RESULTS_AVAILABLE_ACTION) { // 检查扫描是否成功更新 val isUpdated = intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false) if (isUpdated) { // 拿到扫描结果,转成ArrayList val scanResults = ArrayList(wifiManager.scanResults) callback.onScanSuccess(scanResults) } else { callback.onScanFailed() } // 扫描完成后立刻注销接收器,避免内存泄漏 context?.unregisterReceiver(this) } } } // 注册接收器,然后启动扫描 context.registerReceiver(scanReceiver, scanFilter) val scanStarted = wifiManager.startScan() // 如果扫描启动失败,直接回调失败并注销接收器 if (!scanStarted) { context.unregisterReceiver(scanReceiver) callback.onScanFailed() } }
3. 调用扫描方法,在回调里处理结果
// 比如在Activity里调用 scanWifi(this, object : WifiScanCallback { override fun onScanSuccess(results: ArrayList<ScanResult>) { // 这里的results就是填充好的扫描结果列表啦! Log.i("WiFi扫描", "拿到${results.size}条结果") // 后续可以更新UI、存储数据等 } override fun onScanFailed() { Log.e("WiFi扫描", "扫描启动失败,请检查权限和WiFi状态") } })
必加的权限提醒
别忘了在AndroidManifest.xml里声明权限,Android 6.0+还要动态申请位置权限(因为扫描WiFi需要位置服务支持):
<!-- WiFi基础权限 --> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <!-- Android 6.0+ 位置权限 --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
另外,Android 10及以上的设备,需要用户开启位置服务才能正常扫描到WiFi热点哦。
内容的提问来源于stack exchange,提问作者Frankie
相关产品推荐
相关产品推荐

