如何从 StreamBuilder 访问快照?
How to access Snapshot out of the StreamBuilder?
我正在使用 BLOC 从 API 中获取电影。我能够访问 StreamBuilder 小部件内的 bloc,但我在 AppBar[=] 上也有一个 share 按钮 23=] 需要 movie.slug 来显示共享选项。但由于 AppBar 不在 StreamBuilder 中,我无法共享 link。 AppBar 是否可以访问 StreamBuilder Snapshot?
这是页面代码:
import 'package:cinemax_app/src/blocs/movie_bloc.dart';
import 'package:cinemax_app/src/components/movie/movie_header.dart';
import 'package:cinemax_app/src/models/movie.dart';
import 'package:flutter/material.dart';
import 'package:share/share.dart';
import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';
class MoviePage extends StatefulWidget {
final int movieId;
MoviePage({ this.movieId });
@override
_MoviePageState createState() => _MoviePageState();
}
class _MoviePageState extends State<MoviePage> {
MovieModel _movie;
@override
Widget build(BuildContext context) {
movieBloc.fetchMovie(widget.movieId);
return Scaffold(
body: SafeArea(
child: Stack(
children: <Widget>[
StreamBuilder(
stream: movieBloc.movie,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
_movie = snapshot.data as MovieModel;
return ListView(
children: <Widget>[
MovieHeader(movie: _movie),
Container(
padding: EdgeInsets.only(top: 45, bottom: 15, left: 15, right: 15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Sinopse:', style: Theme.of(context).textTheme.title),
HtmlWidget(
_movie.sinopsis,
bodyPadding: EdgeInsets.only(top: 15),
textStyle: TextStyle(color: Colors.grey),
)
],
),
)
]
);
}
return Center(child: CircularProgressIndicator());
},
),
AppBar(
backgroundColor: Colors.transparent,
elevation: 0.0,
actions: <Widget>[
PopupMenuButton(
icon: Icon(Icons.more_vert),
itemBuilder: (BuildContext context) {
return <PopupMenuItem>[
PopupMenuItem(
child: GestureDetector(
child: Text('Partilhar'),
onTap: () {
final movieSLug = _movie.slug;
// prints: 'https://cinema.com/movie/null';
final movieAddress = 'https://cinema.com/movie/${movieSLug}';
Share.share(movieAddress);
},
),
)
];
},
)
],
),
]
),
),
);
}
}
我做错了什么?
您可以摆脱 Stack 并使 StreamBuilder 成为 Scaffold 的父级,这样包括应用栏在内的整个 Scaffold 都可以访问快照。
像这样
class MoviePage extends StatefulWidget {
final int movieId;
MoviePage({this.movieId});
@override
_MoviePageState createState() => _MoviePageState();
}
class _MoviePageState extends State<MoviePage> {
MovieModel _movie;
@override
void initState() {
super.initState();
movieBloc.fetchMovie(widget.movieId);
}
@override
Widget build(BuildContext context) {
movieBloc.fetchMovie(widget.movieId);
return StreamBuilder(
stream: movieBloc.movie,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
_movie = snapshot.data as MovieModel;
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0.0,
actions: <Widget>[
PopupMenuButton(
icon: Icon(Icons.more_vert),
itemBuilder: (BuildContext context) {
return <PopupMenuItem>[
PopupMenuItem(
child: GestureDetector(
child: Text('Partilhar'),
onTap: () {
final movieSLug = _movie.slug;
// prints: 'https://cinema.com/movie/null';
final movieAddress = 'https://cinema.com/movie/${movieSLug}';
Share.share(movieAddress);
},
),
)
];
},
)
],
),
body: SafeArea(
child: ListView(children: <Widget>[
MovieHeader(movie: _movie),
Container(
padding:
EdgeInsets.only(top: 45, bottom: 15, left: 15, right: 15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Sinopse:',
style: Theme.of(context).textTheme.title),
HtmlWidget(
_movie.sinopsis,
bodyPadding: EdgeInsets.only(top: 15),
textStyle: TextStyle(color: Colors.grey),
)
],
),
)
]),
),
);
}
return Center(child: CircularProgressIndicator());
},
);
}
}
我正在使用 BLOC 从 API 中获取电影。我能够访问 StreamBuilder 小部件内的 bloc,但我在 AppBar[=] 上也有一个 share 按钮 23=] 需要 movie.slug 来显示共享选项。但由于 AppBar 不在 StreamBuilder 中,我无法共享 link。 AppBar 是否可以访问 StreamBuilder Snapshot?
这是页面代码:
import 'package:cinemax_app/src/blocs/movie_bloc.dart';
import 'package:cinemax_app/src/components/movie/movie_header.dart';
import 'package:cinemax_app/src/models/movie.dart';
import 'package:flutter/material.dart';
import 'package:share/share.dart';
import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';
class MoviePage extends StatefulWidget {
final int movieId;
MoviePage({ this.movieId });
@override
_MoviePageState createState() => _MoviePageState();
}
class _MoviePageState extends State<MoviePage> {
MovieModel _movie;
@override
Widget build(BuildContext context) {
movieBloc.fetchMovie(widget.movieId);
return Scaffold(
body: SafeArea(
child: Stack(
children: <Widget>[
StreamBuilder(
stream: movieBloc.movie,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
_movie = snapshot.data as MovieModel;
return ListView(
children: <Widget>[
MovieHeader(movie: _movie),
Container(
padding: EdgeInsets.only(top: 45, bottom: 15, left: 15, right: 15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Sinopse:', style: Theme.of(context).textTheme.title),
HtmlWidget(
_movie.sinopsis,
bodyPadding: EdgeInsets.only(top: 15),
textStyle: TextStyle(color: Colors.grey),
)
],
),
)
]
);
}
return Center(child: CircularProgressIndicator());
},
),
AppBar(
backgroundColor: Colors.transparent,
elevation: 0.0,
actions: <Widget>[
PopupMenuButton(
icon: Icon(Icons.more_vert),
itemBuilder: (BuildContext context) {
return <PopupMenuItem>[
PopupMenuItem(
child: GestureDetector(
child: Text('Partilhar'),
onTap: () {
final movieSLug = _movie.slug;
// prints: 'https://cinema.com/movie/null';
final movieAddress = 'https://cinema.com/movie/${movieSLug}';
Share.share(movieAddress);
},
),
)
];
},
)
],
),
]
),
),
);
}
}
我做错了什么?
您可以摆脱 Stack 并使 StreamBuilder 成为 Scaffold 的父级,这样包括应用栏在内的整个 Scaffold 都可以访问快照。
像这样
class MoviePage extends StatefulWidget {
final int movieId;
MoviePage({this.movieId});
@override
_MoviePageState createState() => _MoviePageState();
}
class _MoviePageState extends State<MoviePage> {
MovieModel _movie;
@override
void initState() {
super.initState();
movieBloc.fetchMovie(widget.movieId);
}
@override
Widget build(BuildContext context) {
movieBloc.fetchMovie(widget.movieId);
return StreamBuilder(
stream: movieBloc.movie,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
_movie = snapshot.data as MovieModel;
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0.0,
actions: <Widget>[
PopupMenuButton(
icon: Icon(Icons.more_vert),
itemBuilder: (BuildContext context) {
return <PopupMenuItem>[
PopupMenuItem(
child: GestureDetector(
child: Text('Partilhar'),
onTap: () {
final movieSLug = _movie.slug;
// prints: 'https://cinema.com/movie/null';
final movieAddress = 'https://cinema.com/movie/${movieSLug}';
Share.share(movieAddress);
},
),
)
];
},
)
],
),
body: SafeArea(
child: ListView(children: <Widget>[
MovieHeader(movie: _movie),
Container(
padding:
EdgeInsets.only(top: 45, bottom: 15, left: 15, right: 15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Sinopse:',
style: Theme.of(context).textTheme.title),
HtmlWidget(
_movie.sinopsis,
bodyPadding: EdgeInsets.only(top: 15),
textStyle: TextStyle(color: Colors.grey),
)
],
),
)
]),
),
);
}
return Center(child: CircularProgressIndicator());
},
);
}
}