我正在创建一个从WordPress其余Api获取帖子的Flutter应用程序,我在MaterialPageRoute内调用获取帖子,当我导航到详细信息屏幕并返回到帖子列表页面时,出现了我的问题,流得到了清除,并在我调用sink.add时替换为新内容,预期的行为是向信息流中添加新帖子。
集团
import 'package:app/src/resources/repository.dart';
import 'package:rxdart/rxdart.dart';
import 'package:flutter_wordpress/flutter_wordpress.dart' as wp;
class PostsBloc {
final Repository _repository = Repository();
// Also tried PublishSubject
final _posts = BehaviorSubject<List<wp.Post>>();
int page = 1;
// Getters to Streams
Observable<List<wp.Post>> get posts => _posts.stream;
fetchMorePosts() async {
final posts = await _repository.fetchMorePosts(page);
_posts.sink.add(posts);
page ++; //Temporary, this will be replaced with load more
}
dispose() {
_posts.close();
}
}
提供商
import 'package:flutter/material.dart';
import 'package:app/src/blocs/post_bloc.dart';
export 'package:app/src/blocs/post_bloc.dart';
class PostsProvider extends InheritedWidget {
final PostsBloc bloc;
PostsProvider({Key key, Widget child})
: bloc = PostsBloc(),
super(key: key, child: child);
@override
bool updateShouldNotify(InheritedWidget oldWidget) {
return true;
}
static PostsBloc of(BuildContext context) {
return (context.inheritFromWidgetOfExactType(PostsProvider)
as PostsProvider)
.bloc;
}
}
主要
import 'package:flutter/material.dart';
import 'package:app/src/app.dart';
void main() => runApp(App());
应用
import 'package:flutter/material.dart';
import 'package:app/src/screens/web_view.dart';
import 'package:app/src/blocs/posts_provider.dart';
import 'package:app/src/screens/post_list.dart';
import 'package:app/src/widgets/post_details.dart';
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return PostsProvider(
child: MaterialApp(
theme: ThemeData(
// adding a theme
brightness: Brightness.dark, //changing the theme to dark
primaryColor: Colors.black, // color change for links
accentColor: Colors.green[800], // i dont know
),
title: 'App Title',
onGenerateRoute: buildRoutes,
),
);
}
Route buildRoutes(RouteSettings settings) {
if (settings.name == '/') {
return MaterialPageRoute(
builder: (context) {
final storiesBloc = PostsProvider.of(context);
storiesBloc.fetchMorePosts();
return PostList();
},
);
} else if (settings.name == '/url') {
return MaterialPageRoute(builder: (context) {
return WebViewScreen(url: settings.arguments);
});
}
return MaterialPageRoute(builder: (context) {
return PostDetails(post: settings.arguments);
});
}
}
帖子列表
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:app/src/blocs/posts_provider.dart';
import 'package:flutter_wordpress/flutter_wordpress.dart' as wp;
class PostList extends StatelessWidget {
@override
Widget build(BuildContext context) {
final bloc = PostsProvider.of(context);
//print('im called');
return Scaffold(
appBar: AppBar(
title: Text('Latest Posts'),
),
body: _buildPostList(bloc),
);
}
Widget _buildPostList(PostsBloc bloc) {
return StreamBuilder(
stream: bloc.posts,
//initialData: initialData ,
builder: (BuildContext context, AsyncSnapshot<List<wp.Post>> snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return _buildPostCard(context, post: snapshot.data[index]);
},
);
},
);
}
Widget _buildPostCard(BuildContext context, {wp.Post post}) {
String title = post.title.rendered;
wp.Media featuredMedia = post.featuredMedia;
var id = post.id;
String date = post.date;
return /*Hero(
tag: 'hero$id',
child:*/
Container(
margin: EdgeInsets.all(3),
height: 200,
child: InkWell(
onTap: () =>
{Navigator.pushNamed(context, '/post/$id', arguments: post)},
child: Card(
color: Colors.white,
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child: Container(
padding: EdgeInsets.all(14),
decoration: BoxDecoration(
image: DecorationImage(
colorFilter: ColorFilter.mode(
Colors.black54.withOpacity(0.5), BlendMode.hardLight),
fit: BoxFit.cover,
// image: NetworkImage(featuredMedia.sourceUrl)),
image: CachedNetworkImageProvider(featuredMedia.sourceUrl)),
// ),
//,
),
child: _columnWithContent(title, date),
),
)),
),
// ),
);
}
_columnWithContent(String title, String date) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
_headerItemBuild(title),
_dateItemBuild(date),
],
);
}
_headerItemBuild(String title) {
return Row(
children: <Widget>[
Flexible(
child: Column(
children: <Widget>[
Text(
title,
style: TextStyle(color: Colors.white, fontSize: 18),
)
],
),
),
Container(
child: Row(
children: <Widget>[
// IconButton(
// icon: Icon(
// Icons.share,
// color: Theme.of(context).accentColor,
// ),
// onPressed: () {
// //Share.share(widget.model.url);
// },
// ),
/*IconButton(
icon: Icon(
icons,
color: Theme.of(context).accentColor,
),
onPressed: () => _likeUiLogi(),
),*/
],
),
),
],
);
}
_dateItemBuild(String date) {
//print(date);
// Parse date to normal format
DateFormat format = DateFormat("yyyy-MM-dd'T'HH:mm:ss");
final unformedDate = format.parse(date);
Duration difference = unformedDate.difference(DateTime.now());
return Container(
padding: EdgeInsets.only(top: 12),
child: Text(
(int.tryParse(difference.inHours.abs().toString()) < 12)
? difference.inHours.abs().toString() + " hours ago"
: difference.inDays.abs().toString() + " days ago",
style: TextStyle(color: Colors.white, fontWeight: FontWeight.w600),
),
alignment: Alignment.centerLeft,
);
}
}
// final paddingCardsList = EdgeInsets.symmetric(vertical: 4.0, horizontal: 8.0);
帖子详细信息
import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';
import 'package:flutter_wordpress/flutter_wordpress.dart' as wp;
import 'package:cached_network_image/cached_network_image.dart';
import 'package:intl/intl.dart';
class PostDetails extends StatelessWidget {
final wp.Post post;
PostDetails({Key key, this.post}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: postTitle(post),
),
body: new Padding(
padding: EdgeInsets.all(16.0),
child: new ListView(
children: <Widget>[
Column(
children: <Widget>[
//Hero(tag: 'hero${post.id}', child: hawalImage(post)),
hawalImage(post),
hawalTitle(post),
Row(
children: <Widget>[
Expanded(
child: hawalAuthor(post),
),
Expanded(
child: hawalDate(post),
),
],
),
Divider(),
contentRendered(context, post),
],
),
],
)),
);
}
Widget postTitle(wp.Post post) {
//print(post.title.rendered);
return Padding(
padding: EdgeInsets.symmetric(vertical: 10.0),
child: // Text("data")
Html(
data: post.title.rendered,
defaultTextStyle:
TextStyle(fontSize: 20.0, decoration: TextDecoration.none)),
);
}
Widget hawalImage(wp.Post post) {
return Stack(
children: <Widget>[
Positioned(
bottom: 5.0,
right: 0,
left: 0,
child: Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
spreadRadius: 10,
blurRadius: 20,
color: Colors.black,
offset: new Offset(1.0, 1.0),
),
],
),
),
),
Container(
foregroundDecoration: BoxDecoration(
backgroundBlendMode: BlendMode.overlay,
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
stops: [0.1, 0.5, 0.7, 0.9],
colors: [
// Colors are easy thanks to Flutter's Colors class.
Colors.transparent,
Colors.transparent,
Colors.black45,
Colors.black87,
],
)),
child: CachedNetworkImage(
// width: 200.0,
fadeInCurve: Curves.decelerate,
repeat: ImageRepeat.noRepeat,
fadeInDuration: Duration(milliseconds: 500),
imageUrl: post.featuredMedia.sourceUrl,
placeholder: (context, url) => new CircularProgressIndicator(),
errorWidget: (context, url, error) => new Icon(Icons.error),
),
),
],
);
}
Widget hawalBtnBar() {
return ButtonBar(
children: <Widget>[
IconButton(
icon: Icon(Icons.save),
splashColor: Colors.blueAccent[200],
color: Colors.blueGrey,
tooltip: 'save',
onPressed: () {
//debugPrint("save button tapped");
}, // add +1 to the database
),
IconButton(
icon: Icon(Icons.favorite),
splashColor: Colors.redAccent,
color: Colors.blueGrey,
tooltip: 'like',
onPressed: () {
//debugPrint("favorite button tapped");
}, // add +1 to the database
),
IconButton(
icon: Icon(Icons.share),
color: Colors.blueGrey,
tooltip: 'share',
onPressed: () {
//debugPrint("share button tapped");
}, // Standard share for whatsapp + google + faccebook + twitter
),
],
);
}
Widget hawalTitle(wp.Post post) {
return Padding(
padding: EdgeInsets.symmetric(vertical: 10.0),
child: Html(
data: post.title.rendered,
defaultTextStyle:
TextStyle(fontSize: 20.0, decoration: TextDecoration.none)),
);
}
Widget hawalAuthor(wp.Post post) {
return Text(
"author: " + post.author.name,
textAlign: TextAlign.right,
);
}
Widget hawalDate(wp.Post post) {
return Text(
dateConvertor(post.date),
textAlign: TextAlign.left,
);
}
dynamic dateConvertor(String value) {
//value= "hello";
String convertedValue;
convertedValue = DateFormat('y/M/d H:m').format(DateTime.parse(value));
return convertedValue;
}
Widget contentRendered(BuildContext context, wp.Post post) {
return Html(
data: post.content.rendered,
blockSpacing: 0.0,
renderNewlines: true,
useRichText: true,
onLinkTap: (value) {
Navigator.pushNamed(context, '/url', arguments: value);
},
defaultTextStyle: TextStyle(
// fontFamily: 'NotoKufiArabic',
// fontSize: 20.0,
decoration: TextDecoration.none,
));
}
}