我正在使用RxDart观察更改并相应地更新UI。当应用启动时,我正在进行网络呼叫并成功获取数据,请观察更改并相应地更新UI。但是当我Subjects在关闭屏幕的同时进行配置时。它给出以下错误:
Subjects
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════ I/flutter (15524): The following StateError was thrown while finalizing the widget tree: I/flutter (15524): Bad state: You cannot close the subject while items are being added from addStream
这是bloc类:
class MovieDetailBloc { final _repository = Repository(); final _movieId = PublishSubject<int>(); final _trailers = BehaviorSubject<Future<TrailerModel>>(); Function(int) get fetchTrailersById => _movieId.sink.add; Observable<Future<TrailerModel>> get movieTrailers => _trailers.stream; MovieDetailBloc() { _movieId.stream.transform(_itemTransformer()).pipe(_trailers); } dispose() { _movieId.close(); _trailers.close(); } _itemTransformer() { return ScanStreamTransformer( (Future<TrailerModel> trailer, int id, int index) { print(index); trailer = _repository.fetchTrailers(id); return trailer; }, ); } }
这是我称为这些的UI屏幕:
import 'dart:async'; import 'package:flutter/material.dart'; import '../blocs/movie_detail_bloc_provider.dart'; import '../models/trailer_model.dart'; class MovieDetail extends StatefulWidget { final posterUrl; final description; final releaseDate; final String title; final String voteAverage; final int movieId; MovieDetail({ this.title, this.posterUrl, this.description, this.releaseDate, this.voteAverage, this.movieId, }); @override State<StatefulWidget> createState() { return MovieDetailState( title: title, posterUrl: posterUrl, description: description, releaseDate: releaseDate, voteAverage: voteAverage, movieId: movieId, ); } } class MovieDetailState extends State<MovieDetail> { final posterUrl; final description; final releaseDate; final String title; final String voteAverage; final int movieId; MovieDetailBloc bloc; MovieDetailState({ this.title, this.posterUrl, this.description, this.releaseDate, this.voteAverage, this.movieId, }); @override void didChangeDependencies() { bloc = MovieDetailBlocProvider.of(context); bloc.fetchTrailersById(movieId); super.didChangeDependencies(); } @override void dispose() { bloc.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: NestedScrollView( headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { return <Widget>[ SliverAppBar( expandedHeight: 220.0, floating: false, pinned: false, flexibleSpace: FlexibleSpaceBar( background: Image.network( "https://image.tmdb.org/t/p/w500$posterUrl", fit: BoxFit.cover, )), ), ]; }, body: Padding( padding: const EdgeInsets.all(10.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Container(margin: EdgeInsets.only(top: 5.0)), Text( title, style: TextStyle( fontSize: 25.0, fontWeight: FontWeight.bold, ), ), Container(margin: EdgeInsets.only(top: 8.0, bottom: 8.0)), Row( children: <Widget>[ Icon( Icons.favorite, color: Colors.red, ), Container( margin: EdgeInsets.only(left: 1.0, right: 1.0), ), Text( voteAverage, style: TextStyle( fontSize: 18.0, ), ), Container( margin: EdgeInsets.only(left: 10.0, right: 10.0), ), Text( releaseDate, style: TextStyle( fontSize: 18.0, ), ), ], ), Container(margin: EdgeInsets.only(top: 8.0, bottom: 8.0)), Text(description), Container(margin: EdgeInsets.only(top: 8.0, bottom: 8.0)), Text( "Trailer", style: TextStyle( fontSize: 25.0, fontWeight: FontWeight.bold, ), ), Container(margin: EdgeInsets.only(top: 8.0, bottom: 8.0)), StreamBuilder( stream: bloc.movieTrailers, builder: (context, AsyncSnapshot<Future<TrailerModel>> snapshot) { if (snapshot.hasData) { return FutureBuilder( future: snapshot.data, builder: (context, AsyncSnapshot<TrailerModel> itemSnapShot) { if (itemSnapShot.hasData) { if (itemSnapShot.data.results.length > 0) return trailerLayout(itemSnapShot.data); else return noTrailer(itemSnapShot.data); } else { return CircularProgressIndicator(); } }, ); } else { return CircularProgressIndicator(); } }, ), ], ), ), ), ); } Widget noTrailer(TrailerModel data) { return Center( child: Container( child: Text("No trailer available"), ), ); } } Widget trailerLayout(TrailerModel data) { return Row( children: <Widget>[ Expanded( child: Column( children: <Widget>[ Container( margin: EdgeInsets.all(5.0), height: 100.0, color: Colors.grey, ), Text( data.results[0].name, maxLines: 1, overflow: TextOverflow.ellipsis, ), ], ), ), Expanded( child: Column( children: <Widget>[ Container( margin: EdgeInsets.all(5.0), height: 100.0, color: Colors.grey, ), Text( data.results[1].name, maxLines: 1, overflow: TextOverflow.ellipsis, ), ], ), ), ], ); }
关闭屏幕时出现错误。dispose方法将引发以上异常。我该如何解决这个问题?
我认为排干流应该可以解决问题
dispose() async { _movieId.close(); await _trailers.drain(); _trailers.close(); }
https://api.dartlang.org/stable/2.0.0/dart-async/Stream- class.html