【发布时间】:2019-02-14 19:32:33
【问题描述】:
我有一个小部件来表示按最接近用户当前位置排序的商店列表,也应该应用过滤。
数据在:
- 存储来自 Firestore 集合流的数据
- geolacator 中的当前用户位置。
- 从共享首选项中筛选选项 (可以随时更改)
- 用户选择的列表排序方式
数据输出:过滤、排序、商店列表。
在这种情况下什么模式是最佳实践?
【问题讨论】:
我有一个小部件来表示按最接近用户当前位置排序的商店列表,也应该应用过滤。
数据在:
数据输出:过滤、排序、商店列表。
在这种情况下什么模式是最佳实践?
【问题讨论】:
rxdart : https://pub.dartlang.org/packages/rxdart 如果你想将数据组合在一起,你可以使用
var myObservable = Observable.combineLatest3(
myFirstStream,
mySecondStream,
myThirdStream,
(firstData, secondData, thirdData) => print("$firstData $secondData $thirdData"));
you can combine from ( combineLatest2, combineLatest... combineLatest9 )
或 结合最新流 像这个例子
CombineLatestStream.list<String>([
Stream.fromIterable(["a"]),
Stream.fromIterable(["b"]),
Stream.fromIterable(["C", "D"])])
.listen(print);
【讨论】:
数字 2、3 和 4 是您将通过接收器发送到该集团的输入。该集团监听这些接收器并相应地更新 Firestore 查询。仅此一项就足以让 Firestore 将适当的快照发送到小部件正在侦听的输出流。
如果您无法直接使用 Firestore 的 API 进行排序或过滤,您可以使用 stream.map 或在其上应用 StreamTransformer。转换器通过实现其bind 方法,为您提供了很大的灵活性来侦听流并动态更改或忽略事件。
所以你可以这样做:
Stream<Store> get stores => _firestoreStream
.transform(filter)
.transform(sort);
【讨论】:
根据个人经验,我发现一个块有多个输入会导致难以测试代码。块内隐含的并发问题会导致令人困惑的场景。
我在Adding testing to a Flutter app 帖子中构建它的方式是创建单个输入流,但在消息中添加标记,指出消息属于哪个数据流。它使测试变得理智。
【讨论】:
在这种情况下,我认为有多个异步处理。这个实现可能很复杂。并且存在竞争条件的可能性。
我会如下实现。
希望对你有帮助。
例如:
import 'dart:async';
import 'package:rxdart/rxdart.dart';
class ViewModel {}
class DataFromFirestoreModel {}
abstract class UserControl {}
class UserRequest extends UserControl {}
class UserFilter extends UserControl {
final String keyWord;
UserFilter(this.keyWord);
}
enum SortType { ascending, descending }
class UserSort extends UserControl {
final SortType sortType;
UserSort(this.sortType);
}
class Bloc {
final controller = StreamController<UserControl>();
final viewModel = BehaviorSubject<ViewModel>();
final collection = StreamController<DataFromFirestoreModel>();
Bloc() {
controller.stream.listen(_handleControl);
}
_handleControl(UserControl control) {
if (control is UserRequest) {
_handleRequest();
} else if (control is UserFilter) {
handleFilter(control.keyWord);
} else if (control is UserSort) {
handleSort(control.sortType);
}
}
_handleRequest() {
//get location
//get data from sharedPreferences
//get data from firestore
ViewModel modifiedViewModel; // input modifiedViewModel
viewModel.add(modifiedViewModel);
}
handleSort(SortType sortType) {
final oldViewModel = viewModel.value;
//sorting oldViewModel
ViewModel newViewModel; // input sorted oldViewModel
viewModel.add(newViewModel);
}
handleFilter(String keyWord) {
//store data to sharedPreferences
//get data from Firestore
ViewModel modifiedViewModel; // input modifiedViewModel
viewModel.add(modifiedViewModel);
}
}
【讨论】: