如何使用条形码从 api 中提取信息并将其解析到用户详细信息小部件屏幕 - 在颤振中
Posted
技术标签:
【中文标题】如何使用条形码从 api 中提取信息并将其解析到用户详细信息小部件屏幕 - 在颤振中【英文标题】:how to use bar code to extract information from an api and parse it to a user details widget screen - in flutter 【发布时间】:2020-10-12 13:56:11 【问题描述】:我正在尝试使用条形码来提取用户的信息,例如用户的图片、显示名称和等等……将所有这些数据传递给例如 userDetails 小部件页面。因此,在扫描条形码并提取数据后。它应该使用 Navigator 类进行导航。如果没有这个 api,我会扫描任何内容并将其解析到详细信息页面,但是当我尝试做真实的事情时,它不起作用说字符串不能分配给参数类型。请有人可以帮助我已经尝试了 3 天。这是基本网址:https://jsonplaceholder.typicode.com/Albums 我正在尝试将其用于演示目的。这是我编码成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,
;
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】:您可以在下面复制粘贴运行完整代码 假设条码扫描结果返回“1”,我用下面的代码sn-p来模拟
Future<ScanResult> simulateBarcodeScan()
Future.delayed(Duration(seconds: 3), () );
return Future.value(ScanResult(rawContent: "1"));
第 1 步:不能将 FutureBuilder
放入 _scanQR()
第二步:_scanQR()
代码sn-p
Future<Album> _scanQR() async
try
//ScanResult qrResult = await BarcodeScanner.scan();
ScanResult qrResult = await simulateBarcodeScan();
print(qrResult.rawContent);
_future = httpService.getAlbums(qrResult.rawContent);
setState(() );
第三步:你可以用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(),
);
【讨论】:
哦,我很感激。非常感谢。谢谢你,再次感谢@chunhunghan,我非常感激。【参考方案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());
,
),
);
【讨论】:
哦,我很感激。非常感谢。谢谢你,再次感谢你。以上是关于如何使用条形码从 api 中提取信息并将其解析到用户详细信息小部件屏幕 - 在颤振中的主要内容,如果未能解决你的问题,请参考以下文章
使用 JMeter,如何从 API 的响应正文中提取字符串并将其保存到 csv 文件?
如何使用新的 Google Vision API 生成条形码并将其转换为位图?
使用公共 API 从站点中提取 JSON 数据并将其异步显示在页面上