如何从扫描的BLE结果中创建列表

发布于 2025-01-25 03:11:07 字数 1439 浏览 2 评论 0原文

作为在此处提出的问题的倒置如何将Flow< list< object; ; object> 我想将我的flow< object>转换为flow flow< list< object>>>

至少我认为我想要那个,所以我尝试解释我想实现的目标并提供一些背景。我正在研究使用蓝牙扫描并连接到BLE设备的Android应用程序。我是Android平台和Kotlin的新手,因此尽管我已经学到了很多东西,但我并没有完全掌握所有细节。

我的存储库有一种方法,该方法可以从蓝牙适配器中返回一系列扫描仪:

fun bluetoothScan(): Flow<ScanResult> {
    return bluetoothStack.bluetoothScan()
}

我的ViewModel会消耗该功能,将数据映射到我的BlescanResult中,并将其返回为Livedata。

val scanResults: LiveData<BleScanResult> =
    scanEnabled.flatMapLatest { doScan ->
        if (doScan) {
            repository.bluetoothScan().map { BleScanResult(it.device.name, it.device.address) }
        } else {
            emptyFlow()
        }
    }.asLiveData()

在我的活动中,我想观察该数据并在recyclerview中显示:

val adapter = ScanResultListAdapter()
binding.rcBleScanResults.adapter = adapter

viewModel.scanResults.observe(this) { result ->
    //result.let { adapter.submitList(it) }
}

问题是scanresults来自类型flow&lt; blescanresult&gt;,而不是flow lt&lt; list&lt; blescanresult&gt;&gt;,因此呼叫adapter.submitlist(it)将错误作为 it 预计为列表。

那么,如何将Flow转换为flow&lt; list&gt;(使用重复的其他过滤)?还是我想念流/寿命的概念?

as invers to the question asked here How to convert Flow<List<Object>> to Flow<Object> I want to convert my Flow<Object> to Flow<List<Object>>.

At least I think I want that, so I try to explain what I want to achieve and give some background. I am working on an Android application that uses bluetooth to scan and connect to BLE devices. I'm fairly new to the Android platform and kotlin so I haven't quite grasped all the details despite all the many things I've already learnt.

My repository has a method which returns a Flow of ScanResults from the bluetooth adapter:

fun bluetoothScan(): Flow<ScanResult> {
    return bluetoothStack.bluetoothScan()
}

My ViewModel consumes that function, maps the data to my BleScanResult and returns it as LiveData.

val scanResults: LiveData<BleScanResult> =
    scanEnabled.flatMapLatest { doScan ->
        if (doScan) {
            repository.bluetoothScan().map { BleScanResult(it.device.name, it.device.address) }
        } else {
            emptyFlow()
        }
    }.asLiveData()

In my activity I want to observer on that data and display it in a RecyclerView:

val adapter = ScanResultListAdapter()
binding.rcBleScanResults.adapter = adapter

viewModel.scanResults.observe(this) { result ->
    //result.let { adapter.submitList(it) }
}

The problem is that scanResults is from type Flow<BleScanResult> and not Flow<List<BleScanResult>>, so the call to adapter.submitList(it) throws an error as it is expected to be a list.

So, how do I convert Flow to Flow<List> (with additional filtering of duplicates)? Or is there something I miss about the conception of Flow/LiveData?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

厌味 2025-02-01 03:11:07

您可以尝试使用mutablelist并用您获得的数据填充flow,类似以下内容:

val results: MutableList<BleScanResult> = mutableListOf()
val scanResults: LiveData<List<BleScanResult>> =
    scanEnabled.flatMapLatest { doScan ->
        if (doScan) {
            repository.bluetoothScan().map { 
                results.apply { 
                    add(BleScanResult(it.device.name, it.device.address)) 
                } 
            }
        } else {
            emptyFlow()
        }
    }.asLiveData()

您还可以使用mutableset而不是mutablelist如果要拥有一个唯一的项目列表(假设blescanresultdata class)。

You can try to use a MutableList and fill it with the data you get form a Flow, something like the following:

val results: MutableList<BleScanResult> = mutableListOf()
val scanResults: LiveData<List<BleScanResult>> =
    scanEnabled.flatMapLatest { doScan ->
        if (doScan) {
            repository.bluetoothScan().map { 
                results.apply { 
                    add(BleScanResult(it.device.name, it.device.address)) 
                } 
            }
        } else {
            emptyFlow()
        }
    }.asLiveData()

You can also use a MutableSet instead of MutableList if you want to have a unique list of items (assuming BleScanResult is a data class).

指尖凝香 2025-02-01 03:11:07

您可以使用livedata构建器将流的值收集到mutablelist中。

在这里,我使用TOLIST()在发射它之前复制Mutablelist,因为RecyClerview适配器在可变数据源方面效果不佳。

val scanResults: LiveData<List<BleScanResult>> = liveData {
    val cumulativeResults = mutableListOf<BleScanResult>()

    scanEnabled.flatMapLatest { doScan ->
        if (doScan) {
            repository.bluetoothScan().map { BleScanResult(it.device.name, it.device.address) }
        } else {
            emptyFlow()
        }
    }.collect {
        cumulativeResults += it
        emit(cumulativeResults.toList())
    }
}

如果要避免重复条目并重新排序条目,则可以使用这样的集合:

val scanResults: LiveData<List<BleScanResult>> = liveData {
    val cumulativeResults = mutableSetOf<BleScanResult>()

    scanEnabled.flatMapLatest { doScan ->
        if (doScan) {
            repository.bluetoothScan().map { BleScanResult(it.device.name, it.device.address) }
        } else {
            emptyFlow()
        }
    }.collect {
        if (it !in cumulativeResults) {
            cumulativeResults += it
            emit(cumulativeResults.toList())
        }
    }
}

You could use the liveData builder to collect the Flow's values into a MutableList.

Here I copy the MutableList using toList() before emitting it since RecyclerView Adapters don't play well with mutable data sources.

val scanResults: LiveData<List<BleScanResult>> = liveData {
    val cumulativeResults = mutableListOf<BleScanResult>()

    scanEnabled.flatMapLatest { doScan ->
        if (doScan) {
            repository.bluetoothScan().map { BleScanResult(it.device.name, it.device.address) }
        } else {
            emptyFlow()
        }
    }.collect {
        cumulativeResults += it
        emit(cumulativeResults.toList())
    }
}

If you want to avoid duplicate entries and reordering of entries, you can use a set like this:

val scanResults: LiveData<List<BleScanResult>> = liveData {
    val cumulativeResults = mutableSetOf<BleScanResult>()

    scanEnabled.flatMapLatest { doScan ->
        if (doScan) {
            repository.bluetoothScan().map { BleScanResult(it.device.name, it.device.address) }
        } else {
            emptyFlow()
        }
    }.collect {
        if (it !in cumulativeResults) {
            cumulativeResults += it
            emit(cumulativeResults.toList())
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文