Flutter / Dart 没有从本地托管的烧瓶 api 返回值

Posted

技术标签:

【中文标题】Flutter / Dart 没有从本地托管的烧瓶 api 返回值【英文标题】:Flutter / Dart not returning a value from a locally hosted flask api 【发布时间】:2020-03-27 13:45:09 【问题描述】:

使用 ios、Visual Studio Code、Flask、VirtualEnv....

我刚刚开始使用 Flask 和 Flutter。我创建了一个本地托管的烧瓶服务器,它通过 api 返回用户,我正在尝试使用我的 USB 连接的 IOS 设备使用 Flutter 访问 api。当我尝试托管在互联网上的 api 时,我在手机上得到了输出,但是当我指向本地 API 时,它看起来不像是在访问服务器,我在烧瓶服务器日志中没有得到任何响应,说明发出了请求。我做错了什么?

通过我的浏览器,我可以导航到 127.0.0.1:5000/users 并获得以下输出。我希望这会出现在我的手机上:

[“姓名”:“尼克”,“年龄”:42,“职业”:“网络工程师”, “姓名”:“埃尔文”,“年龄”:32,“职业”:“业务分析师”, “姓名”:“尼克”,“年龄”:22,“职业”:“测试分析​​师”]

这是我的烧瓶服务器代码:

from flask import Flask
from flask_restful import Api, Resource, reqparse
from flask import jsonify
import json

app = Flask(__name__)
api = Api(app)

users = [
    
        "name": "Nick",
        "age": 42,
        "occupation": "Network Engineer"
    ,
    
        "name": "Elvin",
        "age": 32,
        "occupation": "Business Analyst"
    ,
    
        "name": "Nick",
        "age": 22,
        "occupation": "Test Analyst"
    
]

class User(Resource):
    def get(self, name):
        for user in users:
            if(name ==user["name"]):
                return user, 200
        return "User not found@, 404"

    def post(self, name):
        parser = reqparse.RequestParser()
        parser.add_argument("age")
        parser.add_argument("occupation")
        args = parser.parse_args()

        for user in users:
            if(name == user["name"]):
                return "User with name  already exist".format(name), 400

        user = 
            "name": name,
            "age": args["age"],
            "occupation": args["occupation"]
        
        users.append(user)
        return user, 201

    def put(self, name):
        parser = reqparse.RequestParser()
        parser.add_argument("age")
        parser.add_argument("occupation")
        args = parser.parse_args()

        for user in users:
            if(name == user["name"]):
                user["age"] = args["age"]
                user["occupation"] = args["occupation"]
                return user, 200

        user = 
            "name": name,
            "age": args["age"],
            "occupation": args["occupation"]        
        
        users.append(user)
        return user, 201

    def delete(self, name):
        global users
        users = [user for user in users if user["name"] != name]
        return " is deleted.".format(name), 200

@app.route('/users', methods=['GET'])
def getUsers():
    return json.dumps(users)


api.add_resource(User, "/user/<string:name>")
app.run(debug=True)

这是我的 pubspec.yaml

name: apitest2
description: A new Flutter project.

 version: 1.0.0+1

environment:
  sdk: ">=2.1.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter
  http: ^0.12.0+2

  cupertino_icons: ^0.1.2

dev_dependencies:
  flutter_test:
    sdk: flutter

flutter:


  uses-material-design: true

这是我的 API.dart - 从 127... 更改为我的本地 IP 地址没有任何区别

import 'dart:async';
import 'package:http/http.dart' as http;

const baseUrl = "http://127.0.0.1:5000";
//const baseUrl = "http://192.168.86.24:5000";
//const baseUrl = "https://jsonplaceholder.typicode.com";

class API 
  static Future getUsers() 
    var url = baseUrl + "/users";
    return http.get(url);
  

这是我的 User.dart

class User 
  String name;
  int age;
  String occupation;

  User(String name, int age, String occupation) 
    this.name = name;
    this.age = age;
    this.occupation = occupation;
  

  User.fromJson(Map json)
      : name = json['name'],
        age = json['age'],
        occupation = json['occupation'];

  Map toJson() 
    return 'name': name, 'age': age, 'occupation': occupation;
  

这是我的 Main.dart

import 'dart:convert';
import 'package:apitest2/API.dart';
import 'package:apitest2/User.dart';
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget 
  @override
  build(context) 
    return MaterialApp(
      debugShowCheckedModeBanner: true,
      title: 'My Http App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyListScreen(),
    );
  


class MyListScreen extends StatefulWidget 
  @override
  createState() => _MyListScreenState();


class _MyListScreenState extends State 
  var users = new List<User>();

  _getUsers() 
    API.getUsers().then((response) 
      setState(() 
        Iterable list = json.decode(response.body);
        users = list.map((model) => User.fromJson(model)).toList();
      );
    );
  

  initState() 
    super.initState();
    _getUsers();
  

  dispose() 
    super.dispose();
  

  @override
  build(context) 
    return Scaffold(
        appBar: AppBar(
          title: Text("User List"),
        ),
        body: ListView.builder(
          itemCount: users.length,
          itemBuilder: (context, index) 
            return ListTile(title: Text(users[index].name));
          ,
        ));
  

【问题讨论】:

【参考方案1】:

主要思想

如果我们想从连接到我们局域网的其他计算机或设备向我们的 API 发出 HTTP 请求,我们应该使用开发计算机 IP 地址,0.0.0.0(用于 IPv4 配置)或 ::(用于 IPv6 配置)作为我们的开发服务器所需的 IP 地址。 如果我们将 0.0.0.0 指定为 IPv4 配置所需的 IP 地址,则开发服务器将侦听端口 5000 上的每个接口。

参考以下解决方案,也解决了类似的问题:

https://***.com/a/62371660/10031056

【讨论】:

以上是关于Flutter / Dart 没有从本地托管的烧瓶 api 返回值的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Dart/Flutter 中读取本地图像文件的字节数?

如何使用flutter dart webview渲染本地HTML文件

Flutter 读写本地文件

Dart/flutter:如何在模拟器的本地主机上显示来自 API 的图像

如何在 Dart/flutter 中将视频文件分割成小块?

我的 Flutter web 在本地构建得很好,但在 firebase 托管中不起作用