首页 > 解决方案 > 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();
      }
}

标签: dartstreamflutter

解决方案


您的代码工作正常,除了有一点错误。

当我们第一次打开应用程序时,它会显示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);         
    }

}

结果如下:

在此处输入图像描述


推荐阅读