我正在练习Stream并实现了一个简单的应用程序,该应用程序可以获取图像并显示在屏幕上。
这是我的代码,但是没有显示任何原因?
我正在研究StreamController及其用法,所以我不想使用Future或其他Widget。这种逻辑适用于简单的计数器应用程序。
class MyAppPageState extends State<MyAppPage> {
StreamController<List<String>> _controller = StreamController<List<String>>();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(backgroundColor: Colors.orange),
body: Center(
child: StreamBuilder(
stream: _controller.stream,
builder: (BuildContext context, AsyncSnapshot snapshot) =>
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();
_controller.sink.add(url);
});
}
@override
void dispose() {
_controller.close();
super.dispose();
}
}
答案 0 :(得分:2)
您的代码可以正常工作,但有一点错误。
当我们第一次打开该应用程序时,它将显示一个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);
});
}
}
...
如果您对使用Streams感兴趣,那么我建议您使用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);
}
}
这是结果: