Flutter,StreamController无法从网络获取图像

时间:2019-01-02 09:32:23

标签: dart stream flutter

我正在练习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();
      }
}

1 个答案:

答案 0 :(得分:2)

您的代码可以正常工作,但有一点错误。

当我们第一次打开该应用程序时,它将显示一个NoSuchMethodError,如下所示:

enter image description here

原因是我们尚未检查快照是否已接收到数据。 当流没有输入时,我们可以使用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);         
    }

}

这是结果:

enter image description here