如何使用条形码从 api 中提取信息并将其解析到用户详细信息小部件屏幕 - 在颤动中
how to use bar code to extract information from an api and parse it to a user details widget screen - in flutter
我正在尝试使用条形码来提取用户的信息,例如用户的图片、显示名称等等...将所有这些数据传递到例如 userDetails 小部件页面。因此,在扫描条形码并且数据是 extracted.it 后,应使用导航器 class 进行导航。没有这个 api 我扫描任何东西并将其解析到详细信息页面但是当我尝试做真实的事情时它不起作用说字符串不能分配给参数类型。请有人帮助我已经尝试了 3 天了。这是基础 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。
条码页面:
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,
);
}
}
详情页面:
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),
),
),
),
),
],
),
),
),
);
}
}
模特:
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,
};
}
ApiService 文件:
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.";
}
}
}
您可以复制粘贴 运行 下面的完整代码
假设条码扫描结果return“1”,我用下面的代码片段来模拟
Future<ScanResult> simulateBarcodeScan() {
Future.delayed(Duration(seconds: 3), () {});
return Future.value(ScanResult(rawContent: "1"));
}
第 1 步:您不能将 FutureBuilder
放入 _scanQR()
第 2 步:_scanQR()
代码段
Future<Album> _scanQR() async {
try {
//ScanResult qrResult = await BarcodeScanner.scan();
ScanResult qrResult = await simulateBarcodeScan();
print(qrResult.rawContent);
_future = httpService.getAlbums(qrResult.rawContent);
setState(() {});
第 3 步:您可以使用 addPostFrameCallback
来执行 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();
工作演示
完整代码
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(),
);
}
}
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());
}
},
),
);
}
我正在尝试使用条形码来提取用户的信息,例如用户的图片、显示名称等等...将所有这些数据传递到例如 userDetails 小部件页面。因此,在扫描条形码并且数据是 extracted.it 后,应使用导航器 class 进行导航。没有这个 api 我扫描任何东西并将其解析到详细信息页面但是当我尝试做真实的事情时它不起作用说字符串不能分配给参数类型。请有人帮助我已经尝试了 3 天了。这是基础 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。
条码页面:
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,
);
}
}
详情页面:
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),
),
),
),
),
],
),
),
),
);
}
}
模特:
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,
};
}
ApiService 文件:
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.";
}
}
}
您可以复制粘贴 运行 下面的完整代码
假设条码扫描结果return“1”,我用下面的代码片段来模拟
Future<ScanResult> simulateBarcodeScan() {
Future.delayed(Duration(seconds: 3), () {});
return Future.value(ScanResult(rawContent: "1"));
}
第 1 步:您不能将 FutureBuilder
放入 _scanQR()
第 2 步:_scanQR()
代码段
Future<Album> _scanQR() async {
try {
//ScanResult qrResult = await BarcodeScanner.scan();
ScanResult qrResult = await simulateBarcodeScan();
print(qrResult.rawContent);
_future = httpService.getAlbums(qrResult.rawContent);
setState(() {});
第 3 步:您可以使用 addPostFrameCallback
来执行 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();
工作演示
完整代码
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(),
);
}
}
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());
}
},
),
);
}