dart - Flutter,StreamController 无法从网络中获取图像
问题描述
我正在练习 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();
}
}
解决方案
您的代码工作正常,除了有一点错误。
当我们第一次打开应用程序时,它会显示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);
}
}
结果如下:
推荐阅读
- c# - TCP/UDP 混合连接?
- html - 悬停在按钮上后摆动的段落和 h2
- c# - 如何在 C# Async/Await 应用程序中创建循环服务?
- java - 从 postman 测试 OAuth2 Provider 端点的简单实现
- java - 使用 Java / Postgres 处理日期时间和时区
- node.js - nginx: index.js" 被禁止 (13: Permission denied)
- sql - 根据现有文本的长度在 SQL Server 列中插入字符串
- angular - 从 DataSource Angular MatTable 获取对象
- asp.net - “未知的 Web 方法”Ajax 错误
- wordpress - 如何使用 https 在子目录中正确重定向 Wordpress?