问题
I have an assignment and I have to take data from mysql server into a flutter and pass it to StreamBuilder and I was trying to use the same class we are using it in firebase and now I have problem with passing the data that I already take it from the server into the StreamBuilder and as I remember I have to use a different type of snapshot, any help.
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Server',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.pink,
),
home: MyHomePage(title: 'Flutter Server App'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
get documents => null;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
centerTitle: true,
),
);
}
Future getData() async{
var url = 'https://milk-white-reveille.000webhostapp.com/get.php';
http.Response response = await http.get(url);
var data = jsonDecode(response.body);
print(data.toString());
}
@override
void initState() {
getData();
}
}
class BookList extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new StreamBuilder(
stream: _MyHomePageState.getData().snapshot(),
builder: (BuildContext context, AsyncSnapshot<_MyHomePageState> snapshot) {
if (snapshot.hasData) return new Text('Loading...');
return new ListView(
children: snapshot.data.documents.map((document) {
return new ListTile(
title: new Text(document['title']),
subtitle: new Text(document['type']),
);
}).toList(),
);
},
);
}
}
The new code is this
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'dart:async';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Server',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.pink,
),
home: MyHomePage(title: 'Flutter Server App'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
StreamController _streamController = StreamController();
Timer _timer;
var data;
Future getData() async {
var url = 'https://milk-white-reveille.000webhostapp.com/get.php';
http.Response response = await http.get(url);
String jsonsDataString = response.body.toString(); // toString of Response's body is assigned to jsonDataString
data = jsonDecode(jsonsDataString);
print(data.toString());
//Add your data to stream
_streamController.add(data);
}
@override
void initState() {
getData();
//Check the server every 5 seconds
_timer = Timer.periodic(Duration(seconds: 5), (timer) => getData());
super.initState();
}
@override
void dispose() {
//cancel the timer
if (_timer.isActive) _timer.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Home"),
),
body: new _MySql()
);
}
}
class _MySql extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: StreamBuilder(
stream: _MyHomePageState()._streamController.stream,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData)
return ListView(
children: snapshot.data((data) {
return ListTile(
title: Text(data['title']),
subtitle: Text(data['type']),
);
}).toList(),
);
return CircularProgressIndicator();
},
),
);
}
}
but on the phone screen loading... appearing
this one from terminal
E/flutter (10194): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: FormatException: Unexpected character (at character 1)
E/flutter (10194): connected{"title":"maen","type":"dev"}
回答1:
If you want to use it periodically with StreamBuilder;
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Server',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.pink,
),
home: MyHomePage(title: 'Flutter Server App'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
StreamController _streamController = StreamController();
Timer _timer;
Future getData() async {
var url = 'https://milk-white-reveille.000webhostapp.com/get.php';
http.Response response = await http.get(url);
var data = jsonDecode(response.body);
//Add your data to stream
_streamController.add(data);
}
@override
void initState() {
getData();
//Check the server every 5 seconds
_timer = Timer.periodic(Duration(seconds: 5), (timer) => getData());
super.initState();
}
@override
void dispose() {
//cancel the timer
if (_timer.isActive) _timer.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
centerTitle: true,
),
body: StreamBuilder(
stream: _streamController.stream,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData)
return ListView(
children: snapshot.data.map((document) {
return ListTile(
title: Text(document['title']),
subtitle: Text(document['type']),
);
}).toList(),
);
return Text('Loading...');
},
),
);
}
}
回答2:
You should use FutureBuilder
instead of StreamBuilder
. You don't need to use StreamBuilder
for fetching data from the server, If you don't want to check server periodically. (If you want to use it periodically and with StreamBuilder check my next answer);
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Server',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.pink,
),
home: MyHomePage(title: 'Flutter Server App'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Future getData() async {
var url = 'https://milk-white-reveille.000webhostapp.com/get.php';
http.Response response = await http.get(url);
var data = jsonDecode(response.body);
return data;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
centerTitle: true,
),
body: FutureBuilder(
future: getData(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData)
return ListView(
children: snapshot.data.map((document) {
return ListTile(
title: Text(document['title']),
subtitle: Text(document['type']),
);
}).toList(),
);
return Text('Loading...');
},
),
);
}
}
来源:https://stackoverflow.com/questions/61419688/geting-data-from-mysql-to-streambuilder-flutter