从 Api 登录后,我得到了 json 的响应。现在需要将数组长度显示为我的通知图标的计数。怎么做?

Posted

技术标签:

【中文标题】从 Api 登录后,我得到了 json 的响应。现在需要将数组长度显示为我的通知图标的计数。怎么做?【英文标题】:After logged in from a Api i got a response of json. Now need to show the arrays length as count for my notification icon . How to do it? 【发布时间】:2021-01-31 14:44:30 【问题描述】:

这是我试图在我的应用程序中获取此 json 数据的所有操作代码。 这是我作为响应得到的 json


"user_id": 1,
"user_name": "Mr Admin",
"api_token": "6S3gRnPy55JKWyiOF7SwtYO12waZ8ozSyIHUNs2XSEcMh0DfTbpP5k51y2mL",
"notifications": [
    
        "id": "d54ee0cc-054a-4d51-a53b-5f6f658841ae",
        "type": "App\\Notifications\\HandSlipStatusNotification",
        "notifiable_id": 1,
        "notifiable_type": "App\\User",
        "data": 
            "payment_id": 471,
            "generate_payment_id": "10200471",
            "message": "Hand Slip Settled.",
            "amount": 850
        ,
        "read_at": null,
        "created_at": "2020-10-12 15:50:38",
        "updated_at": "2020-10-12 15:50:38"
    ,
    
        "id": "aedb7880-4201-4805-b017-62242dfed741",
        "type": "App\\Notifications\\HandSlipStatusNotification",
        "notifiable_id": 1,
        "notifiable_type": "App\\User",
        "data": 
            "payment_id": 471,
            "generate_payment_id": "10200471",
            "message": "Hand Slip Disbursed.",
            "amount": 850
        ,
        "read_at": null,
        "created_at": "2020-10-12 15:50:25",
        "updated_at": "2020-10-12 15:50:25"
    ,
    
        "id": "99b433b1-9432-44ae-a57f-fcb4ff92872f",
        "type": "App\\Notifications\\HandSlipStatusNotification",
        "notifiable_id": 1,
        "notifiable_type": "App\\User",
        "data": 
            "payment_id": 471,
            "generate_payment_id": "10200471",
            "message": "Hand Slip Approved.",
            "amount": 850
        ,
        "read_at": null,
        "created_at": "2020-10-12 15:50:08",
        "updated_at": "2020-10-12 15:50:08"
    ,

登录.dart

  import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';

    import '../sharePreference.dart';
    import 'homepage.dart';
    
    
    class Login extends StatefulWidget 
      @override
      _LoginState createState() => _LoginState();
    
    
    class _LoginState extends State<Login> 
    
    var notification ;
      bool isprocesscomplete = false;
      TextEditingController _userController = TextEditingController();
      TextEditingController _passwordController = TextEditingController();
      final _scaffoldKey = GlobalKey<ScaffoldState>();
      String BaseUrl = "my url";
    
    
      @override
      Widget build(BuildContext context) 
        return Scaffold(
          key: _scaffoldKey,
          body: SingleChildScrollView(
            child: Center(
              child: Container(
                padding: EdgeInsets.fromLTRB(20, 100, 20, 20),
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: [
                    Text(
                      "Login",
                      style: TextStyle(fontSize: 32),
                    ),
                    SizedBox(
                      height: 30,
                    ),
                    Card(
                      shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(20),
                      ),
                      child: Container(
                        height: 220,
                        width: MediaQuery.of(context).size.width,
                        decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(20),
                        ),
                        child: Column(
                          children: [
                            Padding(
                              padding: const EdgeInsets.all(30),
                              child: TextField(
                                controller: _userController,
                                decoration: InputDecoration(hintText: "Username"),
                              ),
                            ),
                            Padding(
                              padding: const EdgeInsets.all(30),
                              child: TextField(
                                controller: _passwordController,
                                obscureText: true,
                                decoration: InputDecoration(hintText: "Password"),
                              ),
                            ),
                          ],
                        ),
                      ),
                    ),
                    SizedBox(
                      height: 60,
                      width: MediaQuery.of(context).size.width,
                      child: RaisedButton(
                        color: Colors.lightBlue,
                        onPressed: () 
                          if (_userController.text == "" ||
                              _passwordController.text == "") 
                            final snackBar = SnackBar(
                                content: Text("Enter Username and Password"));
                            _scaffoldKey.currentState.showSnackBar(snackBar);
                           else 
                            signIn(_userController.text, _passwordController.text);
                          
                        ,
                        child: ProgressButton(),
                        shape: RoundedRectangleBorder(
                          borderRadius: new BorderRadius.circular(16),
                        ),
                      ),
                    ),
                    SizedBox(
                      height: 20,
                    ),
                    FlatButton(
                      child: Text("Forgot password"),
                      onPressed: () ,
                    ),
                  ],
                ),
              ),
            ),
          ),
        );
      
    
      Widget ProgressButton() 
        if (isprocesscomplete != false) 
          return CircularProgressIndicator(
              valueColor: AlwaysStoppedAnimation<Color>(Colors.white));
         else 
          return new Text(
            "Sign In",
            style: const TextStyle(
              color: Colors.white,
              fontSize: 15.0,
            ),
          );
        
      
    
      void signIn(String username, String password) async 
        setState(() 
          isprocesscomplete = true;
        );
        var response = await http.post(BaseUrl,
            headers: "Content-Type": "application/json",
            body: json.encode(
              "username": username,
              "password": password,
            ));
    
        Map<String, dynamic> value = json.decode(response.body);
        notification = value["notifications"];
        // print('Response $response.body');
        if (response.statusCode == 200) 
          try 
            ///You don't need it but it will be cool for show progress dialgo for 4 second then redirect even if we get reslut
            Future.delayed(Duration(seconds: 4), () 
              // 5s over make it false
              setState(() 
                isprocesscomplete = false;
              );
            );
    
            Map<String, dynamic> value = json.decode(response.body);
    
    
            print('Response $response.body');
            SharedPrefrence().setToken(value['api_token'].toString());
            SharedPrefrence().setName(value['user_name']);
            SharedPrefrence().setUserId(value['user_id'].toString());
    
            ///This is used when user loged in you can set this true,
            ///next time you open you need to check loginc in main.dart or splashscreen if this is true if it is true then
            ///redirect to home page it is false then redirect to Login page
            ///When you logout the app make sure you set this as false like "SharedPrefrence().setLoggedIn(false);"
            SharedPrefrence().setLoggedIn(true);
    
            ///Redirect to Home page
            Navigator.pushAndRemoveUntil(
                                    context,
                                    MaterialPageRoute(
                                        builder: (context) => HomePage(
                                          user_name: value['user_name'],
                                          api_token: value['api_token'],
                                            id : value['user_id'],
                                          notification: notification,
    
                                        )),
                                    ModalRoute.withName("/login"));
    
           catch (e) 
            e.toString();
            final snackBar =
            SnackBar(content: Text("something wrong,Try again ????"));
            _scaffoldKey.currentState.showSnackBar(snackBar);
          
         else 
          var message = value['error'];
          final snackBar = SnackBar( backgroundColor: Colors.redAccent[700],
              content: Text(message.toString()));
          _scaffoldKey.currentState.showSnackBar(snackBar);
        
      
    

在我的 homepage.dart 页面中,我试图显示我从该 json 获取到我的通知小部件的数组计数。通知应将数组的长度显示为计数。这是我的主页代码。

 import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../sharePreference.dart';
import 'login.dart';
import 'login.dart';

class HomePage extends StatefulWidget 

  String user_name;
  final api_token;
  final id ;
 final  List<dynamic> notification ;
  // List data ;
  HomePage( this.user_name, this.api_token , this.id, this.notification );


  @override
  _HomePageState createState() => _HomePageState();




class _HomePageState extends State<HomePage> 


  String nametoprint;
  String tokentoprint;

  @override
  void initState() 
    super.initState();
    Future name = SharedPrefrence().getName();
    name.then((data) async 
      nametoprint = data;
      print(nametoprint);
    );

    Future token= SharedPrefrence().getToken();
    token.then((data) async 
      tokentoprint= data;
      print(tokentoprint);
    );
  



  int counter = 0;
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("Cash-Management"),
          backgroundColor: Colors.blue,
          actions: [

            new Stack(
              children: <Widget>[
                new IconButton(icon: Icon(Icons.notifications), onPressed: () 
                  setState(() 
                    counter = 0;
                  );
                ),
                counter != 0 ? new Positioned(
                  right: 11,
                  top: 11,
                  child: new Container(
                    padding: EdgeInsets.all(2),
                    decoration: new BoxDecoration(
                      color: Colors.red,
                      borderRadius: BorderRadius.circular(6),
                    ),
                    constraints: BoxConstraints(
                      minWidth: 14,
                      minHeight: 14,
                    ),
                    child: Text(
                      '$counter',
                      style: TextStyle(
                        color: Colors.white,
                        fontSize: 8,
                      ),
                      textAlign: TextAlign.center,
                    ),
                  ),
                ) : new Container()
              ],
            ),
            IconButton(
                icon: Icon(Icons.exit_to_app),
                onPressed: () 
                  Navigator.push(
                    context,
                    MaterialPageRoute(builder: (context) => Login()),
                  );
                ),
          ],
        ),
        body: ListView(
          children: <Widget>[
            Container(
              height: 200,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: <Widget>[
                  Text(
                    "$widget.user_name",
                    // "  $widget.username ",
                    style: TextStyle(fontSize: 16),
                  ),
                  Text(
                    "$widget.api_token",
                    // "  $widget.username ",
                    style: TextStyle(fontSize: 16),
                  ),
                  Text(
                    "$widget.id",
                    // "  $widget.username ",
                    style: TextStyle(fontSize: 16),
                  ),
                  Text(" $nametoprint "),
                  Text("$nametoprint"),
                  Text("$tokentoprint"),
                ],
              ),
            ),

Container(
  color: Colors.blue,
  height: 300,
  child:   ListView.builder(
      itemCount: widget.notification == null ?  0 : widget.notification.length,
      itemBuilder: (context, index)
        return ListTile(
          title: Text(widget.notification[index] ["id"]),
          subtitle: Text(widget.notification[index]["type"]),

        );
      ),
),



          ],
        ),

        floatingActionButton: FloatingActionButton(onPressed: () 
          print("Increment Counter");
          setState(() 
            counter++;
          );
        , child: Icon(Icons.add),),
      ),
    );
  

我已经为那个 json 添加了响应模型。 responsemodel.dart

  class UserDetails 
  int userId;
  String userName;
  String apiToken;
  List<Notifications> notifications;

  UserDetails(this.userId, this.userName, this.apiToken, this.notifications);

  UserDetails.fromJson(Map<String, dynamic> json) 
    userId = json['user_id'];
    userName = json['user_name'];
    apiToken = json['api_token'];
    if (json['notifications'] != null) 
      notifications = new List<Notifications>();
      json['notifications'].forEach((v) 
        notifications.add(new Notifications.fromJson(v));
      );
    
  

  Map<String, dynamic> toJson() 
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['user_id'] = this.userId;
    data['user_name'] = this.userName;
    data['api_token'] = this.apiToken;
    if (this.notifications != null) 
      data['notifications'] =
          this.notifications.map((v) => v.toJson()).toList();
    
    return data;
  


class Notifications 
  String id;
  String type;
  int notifiableId;
  String notifiableType;
  Data data;
  Null readAt;
  String createdAt;
  String updatedAt;

  Notifications(
      this.id,
        this.type,
        this.notifiableId,
        this.notifiableType,
        this.data,
        this.readAt,
        this.createdAt,
        this.updatedAt);

  Notifications.fromJson(Map<String, dynamic> json) 
    id = json['id'];
    type = json['type'];
    notifiableId = json['notifiable_id'];
    notifiableType = json['notifiable_type'];
    data = json['data'] != null ? new Data.fromJson(json['data']) : null;
    readAt = json['read_at'];
    createdAt = json['created_at'];
    updatedAt = json['updated_at'];
  

  Map<String, dynamic> toJson() 
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['id'] = this.id;
    data['type'] = this.type;
    data['notifiable_id'] = this.notifiableId;
    data['notifiable_type'] = this.notifiableType;
    if (this.data != null) 
      data['data'] = this.data.toJson();
    
    data['read_at'] = this.readAt;
    data['created_at'] = this.createdAt;
    data['updated_at'] = this.updatedAt;
    return data;
  


class Data 
  int paymentId;
  String generatePaymentId;
  String message;
  int amount;

  Data(this.paymentId, this.generatePaymentId, this.message, this.amount);

  Data.fromJson(Map<String, dynamic> json) 
    paymentId = json['payment_id'];
    generatePaymentId = json['generate_payment_id'];
    message = json['message'];
    amount = json['amount'];
  

  Map<String, dynamic> toJson() 
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['payment_id'] = this.paymentId;
    data['generate_payment_id'] = this.generatePaymentId;
    data['message'] = this.message;
    data['amount'] = this.amount;
    return data;
  

enter image description here

【问题讨论】:

【参考方案1】:

将现有的 json 映射到模型是一种很好的做法,类似于这样

class UserDetails 
  int userId;
  String userName;
  String apiToken;
  List<Notifications> notifications;

  UserDetails(this.userId, this.userName, this.apiToken, this.notifications);

  UserDetails.fromJson(Map<String, dynamic> json) 
    userId = json['user_id'];
    userName = json['user_name'];
    apiToken = json['api_token'];
    if (json['notifications'] != null) 
      notifications = new List<Notifications>();
      json['notifications'].forEach((v) 
        notifications.add(new Notifications.fromJson(v));
      );
    
  

  Map<String, dynamic> toJson() 
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['user_id'] = this.userId;
    data['user_name'] = this.userName;
    data['api_token'] = this.apiToken;
    if (this.notifications != null) 
      data['notifications'] =
          this.notifications.map((v) => v.toJson()).toList();
    
    return data;
  


class Notifications 
  String id;
  String type;
  int notifiableId;
  String notifiableType;
  Data data;
  Null readAt;
  String createdAt;
  String updatedAt;

  Notifications(
      this.id,
      this.type,
      this.notifiableId,
      this.notifiableType,
      this.data,
      this.readAt,
      this.createdAt,
      this.updatedAt);

  Notifications.fromJson(Map<String, dynamic> json) 
    id = json['id'];
    type = json['type'];
    notifiableId = json['notifiable_id'];
    notifiableType = json['notifiable_type'];
    data = json['data'] != null ? new Data.fromJson(json['data']) : null;
    readAt = json['read_at'];
    createdAt = json['created_at'];
    updatedAt = json['updated_at'];
  

  Map<String, dynamic> toJson() 
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['id'] = this.id;
    data['type'] = this.type;
    data['notifiable_id'] = this.notifiableId;
    data['notifiable_type'] = this.notifiableType;
    if (this.data != null) 
      data['data'] = this.data.toJson();
    
    data['read_at'] = this.readAt;
    data['created_at'] = this.createdAt;
    data['updated_at'] = this.updatedAt;
    return data;
  


class Data 
  int paymentId;
  String generatePaymentId;
  String message;
  int amount;

  Data(this.paymentId, this.generatePaymentId, this.message, this.amount);

  Data.fromJson(Map<String, dynamic> json) 
    paymentId = json['payment_id'];
    generatePaymentId = json['generate_payment_id'];
    message = json['message'];
    amount = json['amount'];
  

  Map<String, dynamic> toJson() 
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['payment_id'] = this.paymentId;
    data['generate_payment_id'] = this.generatePaymentId;
    data['message'] = this.message;
    data['amount'] = this.amount;
    return data;
  

转换为Model后,应该访问这个模型,Like,

UserDetails userDetails = new UserDetails(); 

要访问内部的详细信息,您应该执行以下操作。

String name = userDetails.userName; 

这应该可以解决您的问题。

【讨论】:

谢谢兄弟的建议。我在 responsemodel.dart page 创建了模型类。但是很困惑如何在我的主页中的 listview.builder 中显示此通知,或者如何在模型的文本字段中显示单个数据。您可以编辑我的解决方案代码吗?这对我很有帮助。提前致谢。 你能分享一下线框或任何参考 UI,这样我就可以确切地知道你希望 ListView 中的文本字段如何。 我添加了一个ss。问题下。我可以在现有代码中获取一些数据。但现在我想按照你的建议获取数据。基本上我想知道如何使用模型在我的主页中以文本或 listview.builder 显示数据。如果你能帮助我了解你的知识,那将会很有帮助。

以上是关于从 Api 登录后,我得到了 json 的响应。现在需要将数组长度显示为我的通知图标的计数。怎么做?的主要内容,如果未能解决你的问题,请参考以下文章

在颤动中没有得到正确的 api 响应

亚马逊 API JSON 响应

我需要获取 API 以从响应中获取与 POSTMAN 中的结果相同但失败的原始值?

从 JSON 响应中提取浮点密钥对值时出现 TypeError

调用 WCF Web 服务时出现错误的 Json 响应

为啥我从这个请求 iOS JSON 得到空响应