假设我有一个 API - 例如:https ://jsonplaceholder.typicode.com/posts
现在,我想将 StreamBuilder 应用到具有 ListView 的 ListTiles 上。我该如何配置?如何为其创建流?
我完全理解了 firebase 和 firestore 流。我想了解我是否有一个来自 PHP 的 API,并且我想构建一个 StreamBuilder,我该怎么做。
假设我有一个 API - 例如:https ://jsonplaceholder.typicode.com/posts
现在,我想将 StreamBuilder 应用到具有 ListView 的 ListTiles 上。我该如何配置?如何为其创建流?
我完全理解了 firebase 和 firestore 流。我想了解我是否有一个来自 PHP 的 API,并且我想构建一个 StreamBuilder,我该怎么做。
请参考此文档https://blog.khophi.co/using-refreshindicator-with-flutter-streambuilder/
里面还有一段视频
github 代码https://github.com/seanmavley/refreshindicator-with-streambuilder/blob/master/lib/main.dart
完整的示例代码
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:async';
import 'dart:convert';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Basic Project',
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
StreamController _postsController;
final GlobalKey<ScaffoldState> scaffoldKey = new GlobalKey<ScaffoldState>();
int count = 1;
Future fetchPost([howMany = 5]) async {
final response = await http.get(
'https://blog.khophi.co/wp-json/wp/v2/posts/?per_page=$howMany&context=embed');
if (response.statusCode == 200) {
return json.decode(response.body);
} else {
throw Exception('Failed to load post');
}
}
loadPosts() async {
fetchPost().then((res) async {
_postsController.add(res);
return res;
});
}
showSnack() {
return scaffoldKey.currentState.showSnackBar(
SnackBar(
content: Text('New content loaded'),
),
);
}
Future<Null> _handleRefresh() async {
count++;
print(count);
fetchPost(count * 5).then((res) async {
_postsController.add(res);
showSnack();
return null;
});
}
@override
void initState() {
_postsController = new StreamController();
loadPosts();
super.initState();
}
@override
Widget build(BuildContext context) {
return new Scaffold(
key: scaffoldKey,
appBar: new AppBar(
title: new Text('StreamBuilder'),
actions: <Widget>[
IconButton(
tooltip: 'Refresh',
icon: Icon(Icons.refresh),
onPressed: _handleRefresh,
)
],
),
body: StreamBuilder(
stream: _postsController.stream,
builder: (BuildContext context, AsyncSnapshot snapshot) {
print('Has error: ${snapshot.hasError}');
print('Has data: ${snapshot.hasData}');
print('Snapshot Data ${snapshot.data}');
if (snapshot.hasError) {
return Text(snapshot.error);
}
if (snapshot.hasData) {
return Column(
children: <Widget>[
Expanded(
child: Scrollbar(
child: RefreshIndicator(
onRefresh: _handleRefresh,
child: ListView.builder(
physics: const AlwaysScrollableScrollPhysics(),
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
var post = snapshot.data[index];
return ListTile(
title: Text(post['title']['rendered']),
subtitle: Text(post['date']),
);
},
),
),
),
),
],
);
}
if (snapshot.connectionState != ConnectionState.done) {
return Center(
child: CircularProgressIndicator(),
);
}
if (!snapshot.hasData &&
snapshot.connectionState == ConnectionState.done) {
return Text('No Posts');
}
},
),
);
}
}
你在 PHP 中的 json 类
// To parse this JSON data, do
//
// final payload = payloadFromJson(jsonString);
import 'dart:convert';
List<Payload> payloadFromJson(String str) => new List<Payload>.from(json.decode(str).map((x) => Payload.fromJson(x)));
String payloadToJson(List<Payload> data) => json.encode(new List<dynamic>.from(data.map((x) => x.toJson())));
class Payload {
int userId;
int id;
String title;
String body;
Payload({
this.userId,
this.id,
this.title,
this.body,
});
factory Payload.fromJson(Map<String, dynamic> json) => new Payload(
userId: json["userId"],
id: json["id"],
title: json["title"],
body: json["body"],
);
Map<String, dynamic> toJson() => {
"userId": userId,
"id": id,
"title": title,
"body": body,
};
}
经过大量研究,我尝试用下面的代码解决我的问题 此 代码从 API 解决实时数据
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:live_data_stream/provider/Api.dart';
import 'package:live_data_stream/provider/model/AuthModel.dart';
class DetailsView extends StatefulWidget {
@override
_DetailsViewState createState() => _DetailsViewState();
}
class _DetailsViewState extends State<DetailsView> {
StreamController<AuthModel> _userController;
final GlobalKey<ScaffoldState> scaffoldKey = new GlobalKey<ScaffoldState>();
@override
Widget build(BuildContext context) {
return Scaffold(
key: scaffoldKey,
appBar: new AppBar(
title: new Text('StreamBuilder Demo'),
actions: <Widget>[
IconButton(
tooltip: 'Refresh',
icon: Icon(Icons.refresh),
onPressed: _handleRefresh,
)
],
),
body: StreamBuilder(
stream: _userController.stream,
builder: (BuildContext context, AsyncSnapshot<AuthModel> snapshot) {
switch(snapshot.connectionState){
case ConnectionState.none:
return Center(
child: Text('None'),
);
break;
case ConnectionState.waiting:
return Center(
child: CircularProgressIndicator(),
);
break;
case ConnectionState.active:
return Center(
child: Text(
snapshot.data.fname == null ? 'Null' : snapshot.data.fname,
style: Theme.of(context).textTheme.display1,
),
);
break;
case ConnectionState.done:
print('Done is fucking here ${snapshot.data}');
if(snapshot.hasData){
return Center(
child: Text(
snapshot.data.fname == null ? 'Null' : snapshot.data.fname,
style: Theme.of(context).textTheme.display1,
),
);
}else if(snapshot.hasError){
return Text('Has Error');
}else{
return Text('Error');
}
break;
}
return Text('Non in Switch');
},
),
);
}
@override
void initState() {
_userController = new StreamController();
Timer.periodic(Duration(seconds: 1), (_) => loadDetails());
// loadDetails();
super.initState();
}
int count = 1;
loadDetails() async {
Api().getUserInfo('horlaz229@gmail.com', '123456').then((res) async{
print('LoadDetails of ${res.fname}');
_userController.add(res);
return res;
});
}
showSnack() {
return scaffoldKey.currentState.showSnackBar(
SnackBar(
content: Text('New content loaded'),
),
);
}
Future<Null> _handleRefresh() async {
count++;
print(count);
Api().getUserInfo('horlaz229@gmail.com', 'APP-1571216683-766').then((res) async {
print('New Data of ${res.fname}');
_userController.add(res);
showSnack();
return null;
});
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
_userController.close();
}
}
对我有用
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class PeriodicRequester extends StatelessWidget {
Stream<http.Response> getRandomNumberFact() async* {
yield* Stream.periodic(Duration(seconds: 5), (_) {
return http.get("http://numbersapi.com/random/");
}).asyncMap((event) async => await event);
}
@override
Widget build(BuildContext context) {
return StreamBuilder<http.Response>(
stream: getRandomNumberFact(),
builder: (context, snapshot) => snapshot.hasData
? Center(child: Text(snapshot.data.body))
: CircularProgressIndicator(),
);
}
}