Ваш код работает нормально, за исключением небольшой ошибки.
Когда мы открыли приложение в первый раз, оно будет отображать NoSuchMethodError
, например:
Причина в том, что мы не проверили наш снимок, если он уже получил данные или нет.
Мы можем использовать свойство initialData
для предоставления некоторых начальных данных, когда нет потока из потока.
initialData: <List<String>>[],
Нам также нужно написать несколько if
операторов.
if (!snapshot.hasData) return Text('No Data');
if (snapshot.data.length == 0) return Text('No Data');
return Image.network(snapshot.data[0]);
Я изменил ваш код и создал класс BLoC для использования.
Это BLOC:
//somebloc.dart
import "dart:async";
class SomeBloc {
final _data = StreamController<List<String>>();
Stream<List<String>> get data => _data.stream;
final _url = StreamController<List<String>>();
Sink<List<String>> get urlIn => _url.sink;
Stream<List<String>> get urlOut => _url.stream;
SomeBloc() {
urlOut.listen(_handleData);
}
void _handleData(List<String> urlList) {
_data.add(urlList);
}
}
Модифицированная основная:
//main.dart
import "dart:async";
import 'package:http/http.dart' as http;
import 'package:html/parser.dart' as parser;
import 'package:html/dom.dart' as dom;
import "somebloc.dart"; // the bloc
...
class MyAppPageState extends State<MyAppPage> {
@override
Widget build(BuildContext context) {
SomeBloc bloc = SomeBloc();
return Scaffold(
appBar: AppBar(backgroundColor: Colors.orange),
body: Center(
child: StreamBuilder(
stream: bloc.data,
initialData: <List<String>>[],
builder: (BuildContext context, AsyncSnapshot snapshot){
if (!snapshot.hasData) return Text('No Data');
if (snapshot.data.length == 0) return Text('No Data');
return Image.network(snapshot.data[0]);
}
)
),
floatingActionButton: FloatingActionButton(
onPressed: () => _addDataToStream()
),
);
}
void _addDataToStream() {
http.get('https://comic.naver.com/webtoon/weekdayList.nhn?week=mon')
.then((response){
dom.Document document = parser.parse(response.body);
final e = document.querySelectorAll('.img_list .thumb');
List<String> url = e.map((element){
return element.getElementsByTagName('img')[0]
.attributes['src'];
}).toList();
bloc.urlIn.add(url);
});
}
}
...
Если вы заинтересованы в использовании потоков, я бы порекомендовал вам использовать пакет rxdart .
//somebloc.dart using rxdart
import "package:rxdart/rxdart.dart";
import "dart:async";
class SomeBloc {
final _data = BehaviorSubject<List<String>>(); // from rxdart
Stream<List<String>> get data => _data.stream;
final _url = StreamController<List<String>>();
Sink<List<String>> get urlIn => _url.sink;
Stream<List<String>> get urlOut => _url.stream;
SomeBloc() {
urlOut.listen(_handleData);
}
void _handleData(List<String> urlList) {
_data.add(urlList);
}
}
Вот результат: