问题
I am trying to use bar code to extract information of the user for example user's picture, display name and blah blah... pass all those data to for example userDetails widget page. so, after the barcode is scanned and data is extracted.it should navigate using the Navigator class. without this api I scan anything and parse it to the details page but when I tried to do the real thing its not working saying string cannot be assigned to a parameter type. please can somebody help i have been trying it for 3 days now. this is the base url: https://jsonplaceholder.typicode.com/Albums I am trying to use this for demo purpose. And this is the the url I have encoded into https://jsonplaceholder.typicode.com/Albums/1.
Barcode page:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:barcode_scan/barcode_scan.dart';
import 'package:erg_app/api/albumservice.dart';
import 'package:erg_app/AlbumDetails.dart';
import 'package:erg_app/models/album_model.dart';
void main() => runApp(MaterialApp(
debugShowCheckedModeBanner: false,
home: ScanPage(),
));
class ScanPage extends StatefulWidget {
@override
ScanPageState createState() {
return new ScanPageState();
}
}
class ScanPageState extends State<ScanPage> {
String album = '';
final HttpService httpService = HttpService();
Future _scanQR() async {
try {
String qrResult = await BarcodeScanner.scan();
return Scaffold(
body: FutureBuilder(
future: httpService.getAlbums(),
builder: (BuildContext context, AsyncSnapshot<List<Album>> snapshot) {
if (snapshot.hasData) {
List<Album> albums = snapshot.data;
albums.map(
(Album album) =>
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => AlbumDetailsPage(
album : qrResult, // this is the issue
),
),
),
);
} else {
return Center(child: CircularProgressIndicator());
}
},
),
);
} on PlatformException catch (ex) {
if (ex.code == BarcodeScanner.CameraAccessDenied) {
setState(() {
album = "Camera permission was denied";
});
} else {
setState(() {
album = "Unknown Error $ex";
});
}
} on FormatException {
setState(() {
album = "You pressed the back button before scanning anything";
});
} catch (ex) {
setState(() {
album = "Unknown Error $ex";
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('View Album Details'),
iconTheme: IconThemeData(color: Colors.white),
backgroundColor: Colors.green,
),
// body: Center(
// child: Text(
// result,
// style: new TextStyle(fontSize: 30.0, fontWeight: FontWeight.bold),
// ),
// ),
floatingActionButton: FloatingActionButton.extended(
icon: Icon(Icons.camera_alt),
label: Text("Scan Album"),
onPressed: _scanQR,
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
);
}
}
Details Page:
import 'package:erg_app/StartScan.dart';
import 'package:flutter/material.dart';
import 'package:erg_app/models/album_model.dart';
// void main() {
// runApp(ProfilePage());
// }
class AlbumDetailsPage extends StatelessWidget {
final Album album;
AlbumDetailsPage({@required this.album});
@override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: new Center(child: new Text('Album Details:', textAlign: TextAlign.left)),
iconTheme: IconThemeData(color: Colors.white),
backgroundColor: Colors.green,
leading: new IconButton(
icon: new Icon(Icons.assignment_ind),
onPressed: () {},
),
),
// backgroundColor: Colors.green[50],
body: Container(
child: ListView(
children: <Widget>[
Container(margin: EdgeInsets.only(top: 20),),
CircleAvatar(
radius: 80,
backgroundColor: Colors.grey,
// backgroundImage: AssetImage('assets/images/user.png'),
),
Text(
album.title,
style: TextStyle(
fontFamily: 'SourceSansPro',
fontSize: 25,
),
textAlign: TextAlign.center,
),
Text(
'Welcome',
style: TextStyle(
fontSize: 20,
fontFamily: 'SourceSansPro',
color: Colors.green[400],
letterSpacing: 2.5,
),
textAlign: TextAlign.center,
),
Container(margin: EdgeInsets.only(top: 20),),
SizedBox(
height: 20.0,
width: 200,
child: Divider(
color: Colors.teal[100],
),
),
Text(
'Album Details',
textAlign: TextAlign.center,
),
Card(
color: Colors.white,
margin:
EdgeInsets.symmetric(vertical: 10.0, horizontal: 25.0),
child: ListTile(
leading: Text(
'ID:',
style: TextStyle(
fontSize: 20,
fontFamily: 'SourceSansPro',
color: Colors.green[700],
letterSpacing: 2.5,
),
),
title: Text("${album.userId}",
// result,
style:
TextStyle(fontFamily: 'BalooBhai', fontSize: 20.0),
),
),
),
Card(
color: Colors.white,
margin:
EdgeInsets.symmetric(vertical: 10.0, horizontal: 25.0),
child: ListTile(
leading: Text(
'Title:',
style: TextStyle(
fontSize: 20,
fontFamily: 'SourceSansPro',
color: Colors.green[700],
letterSpacing: 2.5,
),
),
title: Text(
album.title,
style:
TextStyle(fontFamily: 'BalooBhai', fontSize: 20.0),
),
),
),
Card(
color: Colors.white,
margin:
EdgeInsets.symmetric(vertical: 10.0, horizontal: 25.0),
child: ListTile(
leading: Text(
'Body:',
style: TextStyle(
fontSize: 20,
fontFamily: 'SourceSansPro',
color: Colors.green[700],
letterSpacing: 2.5,
),
),
title: Text(
album.body,
style:
TextStyle(fontFamily: 'BalooBhai', fontSize: 20.0),
),
),
),
Container(
margin: EdgeInsets.only(top: 20, bottom: 30),
child: Center(
child: RaisedButton(
padding: EdgeInsets.fromLTRB(80, 10, 80, 10),
color: Colors.green,
child: Text("Close", style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 14), ),
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(builder: (context) =>StartScanPage()));
},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
),
),
),
),
],
),
),
),
);
}
}
the Model:
import 'dart:convert';
Album albumFromJson(String str) => Album.fromJson(json.decode(str));
String albumToJson(Album data) => json.encode(data.toJson());
class Album {
Album({
this.userId,
this.id,
this.title,
this.body,
});
int userId;
int id;
String title;
String body;
factory Album.fromJson(Map<String, dynamic> json) => Album(
userId: json["userId"],
id: json["id"],
title: json["title"],
body: json["body"],
);
Map<String, dynamic> toJson() => {
"userId": userId,
"id": id,
"title": title,
"body": body,
};
}
The ApiServiceFile:
import 'dart:convert';
import 'package:http/http.dart';
import 'package:erg_app/models/album_model.dart';
class HttpService {
final String postsURL = "https://jsonplaceholder.typicode.com/Albums";
Future<List<Album>> getAlbums() async {
Response res = await get(postsURL);
if (res.statusCode == 200) {
List<dynamic> body = jsonDecode(res.body);
List<Album> Albums = body
.map(
(dynamic item) => Album.fromJson(item),
)
.toList();
return Albums;
} else {
throw "Can't get Albums.";
}
}
}
回答1:
You can copy paste run full code below
Assume barcode scan result return "1", I use the following code snippet to simulate
Future<ScanResult> simulateBarcodeScan() {
Future.delayed(Duration(seconds: 3), () {});
return Future.value(ScanResult(rawContent: "1"));
}
Step 1: You can not put FutureBuilder
in _scanQR()
Step 2: _scanQR()
code snippet
Future<Album> _scanQR() async {
try {
//ScanResult qrResult = await BarcodeScanner.scan();
ScanResult qrResult = await simulateBarcodeScan();
print(qrResult.rawContent);
_future = httpService.getAlbums(qrResult.rawContent);
setState(() {});
Step 3: You can use addPostFrameCallback
to do Navigate
Album album = snapshot.data;
print(album.toString());
WidgetsBinding.instance.addPostFrameCallback((_) {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) =>
AlbumDetailsPage(album: album // this is the issue
),
),
);
});
return Container();
working demo
full code
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:convert';
import 'package:http/http.dart';
import 'package:barcode_scan/barcode_scan.dart';
class HttpService {
final String postsURL = "https://jsonplaceholder.typicode.com/Albums";
Future<Album> getAlbums(String rawContent) async {
String url = postsURL + "/$rawContent";
print(url);
Response res = await get(url);
print(res.toString());
if (res.statusCode == 200) {
print("in");
return albumFromJson(res.body);
} else {
throw "Can't get Albums.";
}
}
}
Album albumFromJson(String str) => Album.fromJson(json.decode(str));
String albumToJson(Album data) => json.encode(data.toJson());
class Album {
Album({
this.userId,
this.id,
this.title,
this.body,
});
int userId;
int id;
String title;
String body;
factory Album.fromJson(Map<String, dynamic> json) => Album(
userId: json["userId"],
id: json["id"],
title: json["title"],
body: json["body"],
);
Map<String, dynamic> toJson() => {
"userId": userId,
"id": id,
"title": title,
"body": body,
};
}
class ScanPage extends StatefulWidget {
@override
ScanPageState createState() {
return new ScanPageState();
}
}
Future<ScanResult> simulateBarcodeScan() {
Future.delayed(Duration(seconds: 3), () {});
return Future.value(ScanResult(rawContent: "1"));
}
class ScanPageState extends State<ScanPage> {
String album = '';
final HttpService httpService = HttpService();
Future<Album> _scanQR() async {
try {
//ScanResult qrResult = await BarcodeScanner.scan();
ScanResult qrResult = await simulateBarcodeScan();
print(qrResult.rawContent);
_future = httpService.getAlbums(qrResult.rawContent);
setState(() {});
} on PlatformException catch (ex) {
/*if (ex.code == BarcodeScanner.CameraAccessDenied) {
setState(() {
album = "Camera permission was denied";
});
} else {
setState(() {
album = "Unknown Error $ex";
});
}*/
} on FormatException {
/* setState(() {
album = "You pressed the back button before scanning anything";
});*/
} catch (ex) {
/* setState(() {
album = "Unknown Error $ex";
});*/
}
}
Future<Album> _future;
@override
void initState() {
// TODO: implement initState
_future = null;
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('View Album Details'),
iconTheme: IconThemeData(color: Colors.white),
backgroundColor: Colors.green,
),
body: FutureBuilder(
future: _future,
builder: (BuildContext context, AsyncSnapshot<Album> snapshot) {
print(snapshot.connectionState);
switch (snapshot.connectionState) {
case ConnectionState.none:
return Container();
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
case ConnectionState.active:
return Text('');
case ConnectionState.done:
if (snapshot.hasError) {
return Text(
'${snapshot.error}',
style: TextStyle(color: Colors.red),
);
} else {
print("hasdata");
Album album = snapshot.data;
print(album.toString());
WidgetsBinding.instance.addPostFrameCallback((_) {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) =>
AlbumDetailsPage(album: album // this is the issue
),
),
);
});
return Container();
}
}
}),
floatingActionButton: FloatingActionButton.extended(
icon: Icon(Icons.camera_alt),
label: Text("Scan Album"),
onPressed: _scanQR,
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
);
}
}
class AlbumDetailsPage extends StatelessWidget {
final Album album;
AlbumDetailsPage({@required this.album});
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: new Center(
child: new Text('Album Details:', textAlign: TextAlign.left)),
iconTheme: IconThemeData(color: Colors.white),
backgroundColor: Colors.green,
leading: new IconButton(
icon: new Icon(Icons.assignment_ind),
onPressed: () {},
),
),
// backgroundColor: Colors.green[50],
body: Container(
child: ListView(
children: <Widget>[
Container(
margin: EdgeInsets.only(top: 20),
),
CircleAvatar(
radius: 80,
backgroundColor: Colors.grey,
// backgroundImage: AssetImage('assets/images/user.png'),
),
Text(
"${album.title}",
style: TextStyle(
fontFamily: 'SourceSansPro',
fontSize: 25,
),
textAlign: TextAlign.center,
),
Text(
'Welcome',
style: TextStyle(
fontSize: 20,
fontFamily: 'SourceSansPro',
color: Colors.green[400],
letterSpacing: 2.5,
),
textAlign: TextAlign.center,
),
Container(
margin: EdgeInsets.only(top: 20),
),
SizedBox(
height: 20.0,
width: 200,
child: Divider(
color: Colors.teal[100],
),
),
Text(
'Album Details',
textAlign: TextAlign.center,
),
Card(
color: Colors.white,
margin: EdgeInsets.symmetric(vertical: 10.0, horizontal: 25.0),
child: ListTile(
leading: Text(
'ID:',
style: TextStyle(
fontSize: 20,
fontFamily: 'SourceSansPro',
color: Colors.green[700],
letterSpacing: 2.5,
),
),
title: Text(
"${album.userId}",
// result,
style: TextStyle(fontFamily: 'BalooBhai', fontSize: 20.0),
),
),
),
Card(
color: Colors.white,
margin: EdgeInsets.symmetric(vertical: 10.0, horizontal: 25.0),
child: ListTile(
leading: Text(
'Title:',
style: TextStyle(
fontSize: 20,
fontFamily: 'SourceSansPro',
color: Colors.green[700],
letterSpacing: 2.5,
),
),
title: Text(
"${album.title}",
style: TextStyle(fontFamily: 'BalooBhai', fontSize: 20.0),
),
),
),
Card(
color: Colors.white,
margin: EdgeInsets.symmetric(vertical: 10.0, horizontal: 25.0),
child: ListTile(
leading: Text(
'Body:',
style: TextStyle(
fontSize: 20,
fontFamily: 'SourceSansPro',
color: Colors.green[700],
letterSpacing: 2.5,
),
),
title: Text(
"${album.body}",
style: TextStyle(fontFamily: 'BalooBhai', fontSize: 20.0),
),
),
),
Container(
margin: EdgeInsets.only(top: 20, bottom: 30),
child: Center(
child: RaisedButton(
padding: EdgeInsets.fromLTRB(80, 10, 80, 10),
color: Colors.green,
child: Text(
"Close",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 14),
),
onPressed: () {
//Navigator.of(context).push(MaterialPageRoute(builder: (context) =>StartScanPage()));
},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
),
),
),
),
],
),
),
);
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: ScanPage(),
);
}
}
回答2:
this is the exact issue :
Future _scanQR() async {
try {
String qrResult = await BarcodeScanner.scan();
return Scaffold(
body: FutureBuilder(
future: httpService.getAlbums(),
builder: (BuildContext context, AsyncSnapshot<List<Album>> snapshot) {
if (snapshot.hasData) {
List<Album> albums = snapshot.data;
albums.map(
(Album album) =>
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => AlbumDetailsPage(
album : qrResult, // this is the issue
),
),
),
);
} else {
return Center(child: CircularProgressIndicator());
}
},
),
);
}
来源:https://stackoverflow.com/questions/62518934/how-to-use-bar-code-to-extract-information-from-an-api-and-parse-it-to-a-user-de