如何使用条形码从 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(() );

第三步:你可以用addPostFrameCallbackNavigate

  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 生成条形码并将其转换为位图?

如何从数据库中选择数据并将其显示在gridview的新行上

使用公共 API 从站点中提取 JSON 数据并将其异步显示在页面上

如何从 Spotify Search API 获取数据并将其解析为 JSON? [在 node.js 中

从 Matplotlib 图中提取信息并将其显示在 PyQt5 GUI 中