通过字段、方法或 getter 公开 BLOC 流
Exposing BLOC streams via fields, methods, or getter
我正在为我最新的 Flutter 应用程序使用 BLOC 模式,我开始为我的输出流使用类似这样的模式:
class MyBloc {
// Outputs
final Stream<List<Todo>> todos;
factory MyBloc(TodosInteractor interactor) {
final todosController = BehaviorSubject<List<Todo>>()
..addStream(interactor.todos);
return MyBloc._(todosController);
}
MyBloc._(this.todos);
}
但慢慢地我发现自己在做更像这样的事情,一段时间后使用一种方法(或getter):
class MyBloc {
final TodosInteractor _interactor;
// Outputs
Stream<List<Todo>> todos(){
return _interactor.todos;
}
MyBloc(this._interactor) { }
}
想看的人... getter for todos
in TodosInteractor
:
Stream<List<Todo>> get todos {
return repository
.todos()
.map((entities) => entities.map(Todo.fromEntity).toList());
}
当我查看不同的代码时,我看到第一个示例使用字段而不是方法来公开流,但我不明白为什么我会选择一个而不是另一个。在我看来,创建另一个控制器只是为了推动流有点多......除了在我的 todos 流定义中不可变之外,这有什么好处吗?还是我只是吹毛求疵?
好吧,这可能不是最佳答案,但使用 get 方法公开输出流是一种很好的做法。下面是我使用 RxDart 写入项目的 bloc class 示例。
class CityListWidgetBloc {
final _cityInput = PublishSubject<List<Cidade>>();
final _searchInput = new PublishSubject<String>();
final _selectedItemsInput = new PublishSubject<List<Cidade>>();
// exposing stream using get methods
Observable<List<Cidade>> get allCities => _cityInput.stream;
Observable<List<Cidade>> get selectedItems => _selectedItemsInput.stream;
List<Cidade> _searchList = new List();
List<Cidade> _selectedItems = new List();
List<Cidade> _mainDataList;
CityListWidgetBloc() {
//init search stream
_searchInput.stream.listen((searchPattern) {
if (searchPattern.isEmpty) {
_onData(_mainDataList); // resend local data list
} else {
_searchList.clear();
_mainDataList.forEach((city) {
if (city.nome.toLowerCase().contains(searchPattern.toLowerCase())) {
_searchList.add(city);
}
});
_cityInput.sink.add(_searchList);
}
});
}
//getting data from firebase
getCity( {@required String key}) {
FirebaseStateCityHelper.getCitiesFrom(key, _onData);
//_lastKey = key;
}
searchFor(String pattern) {
_searchInput.sink.add(pattern);
}
void _onData(List<Cidade> list) {
_mainDataList = list;
list.sort((a, b) => (a.nome.compareTo(b.nome)));
_cityInput.sink.add(list);
}
bool isSelected(Cidade item) {
return _selectedItems.contains(item);
}
void selectItem(Cidade item) {
_selectedItems.add(item);
_selectedItemsInput.sink.add(_selectedItems);
}
void selectItems(List<Cidade> items){
_selectedItems.addAll( items);
_selectedItemsInput.sink.add( _selectedItems );
}
void removeItem(Cidade item) {
_selectedItems.remove(item);
_selectedItemsInput.sink.add(_selectedItems);
}
dispose() {
_cityInput.close();
_searchInput.close();
_selectedItemsInput.close();
}
}
我正在为我最新的 Flutter 应用程序使用 BLOC 模式,我开始为我的输出流使用类似这样的模式:
class MyBloc {
// Outputs
final Stream<List<Todo>> todos;
factory MyBloc(TodosInteractor interactor) {
final todosController = BehaviorSubject<List<Todo>>()
..addStream(interactor.todos);
return MyBloc._(todosController);
}
MyBloc._(this.todos);
}
但慢慢地我发现自己在做更像这样的事情,一段时间后使用一种方法(或getter):
class MyBloc {
final TodosInteractor _interactor;
// Outputs
Stream<List<Todo>> todos(){
return _interactor.todos;
}
MyBloc(this._interactor) { }
}
想看的人... getter for todos
in TodosInteractor
:
Stream<List<Todo>> get todos {
return repository
.todos()
.map((entities) => entities.map(Todo.fromEntity).toList());
}
当我查看不同的代码时,我看到第一个示例使用字段而不是方法来公开流,但我不明白为什么我会选择一个而不是另一个。在我看来,创建另一个控制器只是为了推动流有点多......除了在我的 todos 流定义中不可变之外,这有什么好处吗?还是我只是吹毛求疵?
好吧,这可能不是最佳答案,但使用 get 方法公开输出流是一种很好的做法。下面是我使用 RxDart 写入项目的 bloc class 示例。
class CityListWidgetBloc {
final _cityInput = PublishSubject<List<Cidade>>();
final _searchInput = new PublishSubject<String>();
final _selectedItemsInput = new PublishSubject<List<Cidade>>();
// exposing stream using get methods
Observable<List<Cidade>> get allCities => _cityInput.stream;
Observable<List<Cidade>> get selectedItems => _selectedItemsInput.stream;
List<Cidade> _searchList = new List();
List<Cidade> _selectedItems = new List();
List<Cidade> _mainDataList;
CityListWidgetBloc() {
//init search stream
_searchInput.stream.listen((searchPattern) {
if (searchPattern.isEmpty) {
_onData(_mainDataList); // resend local data list
} else {
_searchList.clear();
_mainDataList.forEach((city) {
if (city.nome.toLowerCase().contains(searchPattern.toLowerCase())) {
_searchList.add(city);
}
});
_cityInput.sink.add(_searchList);
}
});
}
//getting data from firebase
getCity( {@required String key}) {
FirebaseStateCityHelper.getCitiesFrom(key, _onData);
//_lastKey = key;
}
searchFor(String pattern) {
_searchInput.sink.add(pattern);
}
void _onData(List<Cidade> list) {
_mainDataList = list;
list.sort((a, b) => (a.nome.compareTo(b.nome)));
_cityInput.sink.add(list);
}
bool isSelected(Cidade item) {
return _selectedItems.contains(item);
}
void selectItem(Cidade item) {
_selectedItems.add(item);
_selectedItemsInput.sink.add(_selectedItems);
}
void selectItems(List<Cidade> items){
_selectedItems.addAll( items);
_selectedItemsInput.sink.add( _selectedItems );
}
void removeItem(Cidade item) {
_selectedItems.remove(item);
_selectedItemsInput.sink.add(_selectedItems);
}
dispose() {
_cityInput.close();
_searchInput.close();
_selectedItemsInput.close();
}
}