如何在 Flutter Dio 中将数组作为列表返回

问题描述 投票:0回答:1

当我说我是新手时,我的意思是这是我的第一个 dart 和 flutter 应用程序。这也是我第一次在堆栈交换上发帖。我正在尝试使用 Flutter Dio 使用该数组并将其存储到 sqlite 以用于离线优先应用程序。我收到错误 400 客户端错误。预先感谢

[
    {
        "serverId": 4,
        "documentJobId": 15313,
        "serviceOn": "Jerry Brown                                                                ",
        "deliveryTo": "Jerry Brown                                                                ",
        "street1": "jcincsccncnncnc                                                      ",
        "street2": null,
        "aptSuite": null,
        "city": "nwcwncwcn                      ",
        "state": "MD                  ",
        "zip": "99999     ",
        "returnDate": "2023-12-30T00:00:00"
    },
    {
        "serverId": 4,
        "documentJobId": 15313,
        "serviceOn": "David Brown                                                                ",
        "deliveryTo": "David Brown                                                                ",
        "street1": "ncjcjcncncjncn                                                           ",
        "street2": null,
        "aptSuite": null,
        "city": "Ncncnscn                    ",
        "state": "PA                  ",
        "zip": "99998     ",
        "returnDate": "2023-12-30T00:00:00"
    }

]

这是我尝试过的

location_model.dart

import 'dart:convert';

List<Location> FromJson(String str) =>
    List<Location>.from(json.decode(str).map((x) => Location.fromJson(x)));

String locationToJson(List<Location> data) =>
    json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

//String locationToJson(List<Location> data) => json.encode(data);

class Location {

  int serverId;
  int documentJobId;
  String deliveryTo;
  String serviceOn;
  String street1;
  String? street2;
  String? aptSuite;
  String city;
  String state;
  String zip;
  DateTime returnDate;
 //  double? LonLat;

  Location({

    required this.serverId,
    required this.documentJobId,
    required this.deliveryTo,
    required this.serviceOn,
    required this.street1,
    this.street2,
    this.aptSuite,
    required this.city,
    required this.state,
    required this.zip,
    required this.returnDate,
    //    this.LonLat
  });

  factory Location.fromJson(Map<String, dynamic> json) => Location(
    serverId: json["serverId"],
    documentJobId: json["documentJobId"],
    deliveryTo: json["deliveryTo"],
    serviceOn: json["serviceOn"],
    street1: json["street1"],
    street2: json["street2"],
    aptSuite: json["aptSuite"],
    city: json["city"],
    state: json["state"],
    zip: json["zip"],
    returnDate: DateTime.parse(json["returnDate"]),



  //  LonLat: json["LonLat"]
  );

  Map<String, dynamic> toJson() => {
    "serverId": serverId,
    "documentJobId": documentJobId,
    "deliveryTo": deliveryTo,
    "serviceOn": serviceOn,
    "street1": street1,
    "street2": street2,
    "aptSuite": aptSuite,
    "city": city,
    "state": state,
    "zip": zip,
    "returnDate": returnDate,
 //   "LonLat": LonLat
  };
}

main.dart

import 'package:flutter/material.dart';
import 'package:ppisnet/src/pages/home_page.dart';
import 'dart:io';

class MyHttpOverrides extends HttpOverrides{
  @override
  HttpClient createHttpClient(SecurityContext? context){
    return super.createHttpClient(context)
      ..badCertificateCallback = (X509Certificate cert, String host, int port)=> true;
  }
}

void main() {
  HttpOverrides.global =  MyHttpOverrides();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        debugShowCheckedModeBanner: false,
        initialRoute: 'home',
        routes: {
          'home': (BuildContext context) => HomePage(),
        }
    );
  }
}

location_api_provider.dart

import 'package:ppisnet/src/models/location_model.dart';
import 'package:ppisnet/src/providers/db_provider.dart';
import 'package:dio/dio.dart';

class LocationApiProvider {
  Future<List<Null>> getAllLocations() async {

    var url ="https://############/api/ghsjkjjkjfs";
    Response response = await Dio().get(url);

    return (response.data as List).map((location) {
      print('Inserting $location');
      DBProvider.db.createLocation(Location.fromJson(location));
    }).toList();
  }
}

db_provider.dart

import 'dart:io';
import 'package:ppisnet/src/models/location_model.dart';
import 'package:path/path.dart';

import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';

class DBProvider {
  static Database? _database;
  static final DBProvider db = DBProvider._();

  DBProvider._();

  Future<Database?> get database async {
    // If database exists, return database
    if (_database != null) return _database;

    // If database don't exists, create one
    _database  = await initDB();

    return _database;
  }

  // Create the database and the Employee table
  initDB() async {
    Directory documentsDirectory = await getApplicationDocumentsDirectory();
    final path = join(documentsDirectory.path, 'location_manager.db');

    return await openDatabase(path, version: 1, onOpen: (db) {},
        onCreate: (Database db, int version) async {
          await db.execute('CREATE TABLE Location('
              'DocumentJobId INTEGER PRIMARY KEY,'
              'Street1 TEXT,'
              'Street2 TEXT,'
              'AptSuite TEXT,'
              'City TEXT,'
              'State TEXT,'
              'Zip TEXT'
              'ServeOn TEXT,'
              'DeliveryTo TEXT,'
              'ServerId INTEGER,'
              'LonLat DOUBLE,'
              'ReturnDate DATE'

              ')');
        });
  }

  // Insert employee on database
  createLocation(Location newLocation) async {
    await deleteAllLocations();
    final db = await database;
    final res = await db?.insert('Location', newLocation.toJson());

    return res;
  }

  // Delete all employees
  Future<int?> deleteAllLocations() async {
    final db = await database;
    final res = await db?.rawDelete('DELETE FROM Location');

    return res;
  }

  Future<List<Location>> getAllLocations() async {
    final db = await database;
    final res = await db?.rawQuery("SELECT * FROM Location");

    List<Location> list =
    res!.isNotEmpty ? res.map((c) => Location.fromJson(c)).toList() : [];

    return list;
  }
}

home_page.dart

import 'package:ppisnet/src/providers/db_provider.dart';
import 'package:ppisnet/src/providers/location_api_provider.dart';
import 'package:flutter/material.dart';

class HomePage extends StatefulWidget {


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

class _HomePageState extends State<HomePage> {
  var isLoading = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Api to sqlite'),
        centerTitle: true,
        actions: <Widget>[
          Container(
            padding: EdgeInsets.only(right: 10.0),
            child: IconButton(
              icon: Icon(Icons.settings_input_antenna),
              onPressed: () async {
                await _loadFromApi();
              },
            ),
          ),
          Container(
            padding:  EdgeInsets.only(right: 10.0),
            child: IconButton(
              icon: Icon(Icons.delete),
              onPressed: () async {
                await _deleteData();
              },
            ),
          ),
        ],
      ),
      body: isLoading
          ? Center(
        child: CircularProgressIndicator(),
      )
          : _buildLocationListView(),
    );
  }

  _loadFromApi() async {
    setState(() {
      isLoading = true;
    });

    var apiProvider = LocationApiProvider();
    await apiProvider.getAllLocations();

    // wait for 2 seconds to simulate loading of data
    await Future.delayed(const Duration(seconds: 2));

    setState(() {
      isLoading = false;
    });
  }

  _deleteData() async {
    setState(() {
      isLoading = true;
    });

    await DBProvider.db.deleteAllLocations();

    // wait for 1 second to simulate loading of data
    await Future.delayed(const Duration(seconds: 1));

    setState(() {
      isLoading = false;
    });

    print('All locations deleted');
  }

  _buildLocationListView() {
    return FutureBuilder(
      future: DBProvider.db.getAllLocations(),
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        if (!snapshot.hasData) {
          return Center(
            child: CircularProgressIndicator(),
          );
        } else {
          return ListView.separated(
            separatorBuilder: (context, index) => Divider(
              color: Colors.black12,
            ),
            itemCount: snapshot.data.length,
            itemBuilder: (BuildContext context, int index) {
              return ListTile(
                leading: Text(
                  "${index + 1}",
                  style: TextStyle(fontSize: 20.0),
                ),
                title: Text(
                    "City: ${snapshot.data[index].city} ${snapshot.data[index].state} "),               subtitle: Text('Zip: ${snapshot.data[index].zip}'),
              );
            },
          );
        }
      },
    );
  }
}

E/flutter (13411): [错误:flutter/runtime/dart_vm_initializer.cc(41)] 未处理的异常: DioException [错误响应]: 抛出此异常是因为响应的状态代码为 400 并且配置了 RequestOptions.validateStatus抛出此状态代码。 E/flutter (13411):状态码 400 的含义如下:“客户端错误 - 请求包含错误语法或无法完成” E/flutter (13411):了解有关状态代码的更多信息,请访问 https://developer.mozilla.org/en-US/docs/Web/HTTP/Status E/flutter (13411):为了解决此异常,您通常必须验证并修复您的请求代码,或者必须修复服务器代码。 E/颤振(13411): E/flutter (13411): #0 DioMixin.fetch (包:dio/src/dio_mixin.dart:509:7) E/颤振(13411): E/flutter (13411): #1 LocationApiProvider.getAllLocations (包:ppisnet/src/providers/location_api_provider.dart:9:25) E/颤振(13411): E/flutter (13411): #2 _HomePageState._loadFromApi (包:ppisnet/src/pages/home_page.dart:56:5) E/颤振(13411): E/flutter (13411): #3 _HomePageState.build。 (包:ppisnet/src/pages/home_page.dart:27:17) E/颤振(13411): E/颤动(13411):

arrays flutter sqlite dio
1个回答
0
投票

我认为您的代码没有问题,但是通常格式错误的 URL 是导致 400 错误状态代码的最常见原因。

因此,请再次检查您的网址并确保它是正确的网址。

最好尝试在邮递员上测试 get 方法,甚至使用浏览器来确保它返回数据。

© www.soinside.com 2019 - 2024. All rights reserved.