android - 为什么我的 flutter http 网络调用很慢?

标签 android ios flutter http dart

我正在开发一个带有网络 Activity 的 flutter 应用程序。为了获取数据,我连接到 REST API , 这个 API 应该很快。
有关更多信息,此 API 使用 AWS API GatewayAWS Lambda以及其他 AWS 技术。
下面是我的代码,连接到网络。

class RoleService with ChangeNotifier {
  NavLinks _navLinks = NavLinks();
  late List<Role> _roles;



  /// Get all Roles
  Future<void> getAllRoles(String authToken) async {
    try {
      var data = await http.get(
        Uri.parse("https://api2.example.com/userrel/roles/getall"),
        headers: {HttpHeaders.authorizationHeader: "Bearer $authToken"},
      );
      var jsonData =
          convert.json.decode(data.body).cast<Map<String, dynamic>>();
      _roles = jsonData.map<Role>((json) => new Role.fromJson(json)).toList();
      print(_roles);
    } catch (error) {
      print(error);
      throw error;
    }
  }
}
你可以看到postman上述性能API调用下方电话。对于 flutter 测试,我使用 华为p30精简版安卓手机。
enter image description here
然后,当我执行相同的 API打电话 flutter ,这就是我得到的。
enter image description here
观察 postman 的输出我可以看到它已经缓存了 DNS 查找、TCP 握手和 SSL 握手。 postman 在第一次调用 API 基本 URI 后执行此操作。然后从第 2 次开始,DNS 查找等被缓存,从而在 future 对同一基本 URI 的 API 调用中节省大量时间。
但是在 flutter 中,“建立连接”的时间很长,即使检索数据的时间只有几毫秒。
如何避免连接延迟并获得最佳性能?如果缓存 SSL、DNS 查找等是解决方案,我该如何在 flutter 中做到这一点?

最佳答案

这个问题好像很多人都有。所以,让我回答我自己的问题。
flutter 能记住网络连接吗?是的,它可以。
Flutter 只需要对同一个 API 进行一次网络调用即可记住连接。从第二次调用同一个 API 开始,它将使用它的“缓存”内存,从而大幅提升性能。
所以首先要记住,这只有在你多次调用同一个 API 时才有效。如果您调用不同的 API,这将不起作用。但是,在许多应用程序中,您拥有由 API 团队构建的 API,并且您将调用该应用程序的相同吞吐量。
解决方法是使用 flutter http.Client .然后分享相同的http.Client跨您对同一 API 的调用。您将看到只有第一个调用需要时间进行“连接”,其余调用不需要那个时间。
Flutter http pub page 中提供了一个示例.它说 ,

If you're making multiple requests to the same server, you can keep open a persistent connection by using a Client rather than making one-off requests. If you do this, make sure to close the client when you're done:


检查下面的例子。仅供引用,并非最佳使用方式。
main.dart
import 'package:flutter/material.dart';
import 'package:network_test/role_service.dart';
import 'package:network_test/user_role_service.dart';
import 'package:network_test/user_service.dart';
import 'package:http/http.dart' as http;

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  var startTime = "";
  var endTime = "";

  void _network() async {
    var client = http.Client();

    RoleService _roleService = RoleService();
    UserService _userService = UserService();
    UserRoleService _userRoleService = UserRoleService();

    String authToken = "****";

    String uid = "555555";
    try {
      await _roleService.getAllRoles(authToken, client);
      //await _roleService.getAllRoles(authToken, client);
      await _userService.getUserByUID(authToken, uid, client);
      await _userService.getUserByID(authToken, 27, client);
      await _userRoleService.getUserRoleByUser(authToken, 27, client);
    } finally {
      client.close();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              "Start Time: " + startTime,
              style: Theme.of(context).textTheme.headline4,
            ),
            Text(
              "End Time: " + endTime,
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _network,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}
role_service.dart
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:http/http.dart';
import 'package:network_test/role.dart';
import 'dart:convert' as convert;
import 'dart:io';

class RoleService with ChangeNotifier {
  late List<Role> _roles;
  String link2 = "https://api2.somewhere.com/userrel";

  /// Return roles
  List<Role> returnRoles() {
    return _roles;
  }

  /// Get all Roles
  Future<void> getAllRoles(String authToken, Client client) async {
    try {
      var data = await client.get(Uri.parse(link2 + "/role/getall"),
          headers: {HttpHeaders.authorizationHeader: "Bearer $authToken"});

     
      var jsonData =
          convert.json.decode(data.body).cast<Map<String, dynamic>>();
      _roles = jsonData.map<Role>((json) => Role.fromJson(json)).toList();
      print(_roles[0].roleName);
    } catch (error) {
      print(error);
      throw error;
    }
  }
}
现在我告诉你,以上不是最佳做法。为什么?因为您将创建和销毁 http.Client在许多不同的地方。让我们注意一个更好的做法。
在几乎每个应用程序中,我们都使用状态管理。我是Provider的粉丝,它可以是你选择的任何东西。我想出最好的办法是让状态管理记住http.Client的创建.由于我使用的是 Provider ,我创建了以下类。
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';

class ConnectionService with ChangeNotifier {
  http.Client _client = http.Client();

  http.Client returnConnection() {
    return _client;
  }
}
这是我的主要类(class)
void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();

  runApp(MultiProvider(
    providers: [
      ChangeNotifierProvider(create: (context) => ConnectionService()),
    ],
    child: MyApp(),
  ));
}
现在,当应用程序打开时,我调用 ConnectionService类来建立连接并执行我的 API 调用,例如检查用户身份验证、用户访问等。只有第一个调用需要时间来建立连接,其他调用则不需要。

关于android - 为什么我的 flutter http 网络调用很慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69136187/

相关文章:

android - 键盘隐藏输入(位置:fixed; bottom:0;) with phonegap on android

ios - 上载到App Store connect之后出现Xcode 11.3问题。无法与测试器链接构建

android - 没有权限(plugdev 组中的用户;你的 udev 规则错了吗?)

sqlite - 是否有任何选项可以为 Web 构建运行 SQLite Flutter?

Android 自动启动应用程序

java - FragmentTransaction.commit 上的 Activity 已被销毁

java - 滑动在 Appium Android Webview 中不起作用

javascript - 为什么 String.prototype.replace 从我的字符串中删除 "$' "?

ios - 如何在整个 View 中将 PDFSelection 居中?

json - 如何使用动态数组键解析 json?