美文网首页Flutter
Flutter初步探索(四)网络连接

Flutter初步探索(四)网络连接

作者: 安啡他命 | 来源:发表于2018-12-26 23:41 被阅读50次

    Dart和Flutter提供了工具来完成访问网络连接的工作。

    一、指引

    1. 添加http
    2. 使用http包来生成网络请求
    3. 转换response到一个Dart对象
    4. 使用Flutter展示数据

    1. 添加http

    http 提供了最简单的房还是来访问网络的数据。
    安装http包,我们需要pubspec.yaml增加依赖。我们 可以在[pub website]找到最新的版本来安装(https://pub.dartlang.org/packages/http#-installing-tab-).

    dependencies:
      http: <latest_version>
    
    

    2. 使用http包来生成网络请求

    在这个例子里,我们使用在JSONPlaceholder REST API里面的 http.get()来发送一个请求。

    Future<http.Response> fetchPost() {
      return http.get('https://jsonplaceholder.typicode.com/posts/1');
    }
    
    

    http.get()方法返回包含Response的一个Future

    • Future是Dart类的一个核心同步操作。它用于表示将来某个时候可用的潜在值或错误。

    • http.Response 类包含从成功的http调用接收的数据。

    3. 转换response到一个Dart对象

    虽然很容易发送一个网络请求,但是使用原始的Future<http.Response>并不是很便。为了让我们的更容易处理,可以将http.Response转换为我们自己的Dart对象。

    创建一个Post

    首先,我们需要创建一个包含来自网络请求的数据的Post类。它还将包括一个工厂构造器,允许我们从json创建Post

    手动转换JSON只是其中一个选择。有关更多信息,请参阅关于JSON和序列化

    class Post {
      final int userId;
      final int id;
      final String title;
      final String body;
    
      Post({this.userId, this.id, this.title, this.body});
    
      factory Post.fromJson(Map<String, dynamic> json) {
        return Post(
          userId: json['userId'],
          id: json['id'],
          title: json['title'],
          body: json['body'],
        );
      }
    }
    
    

    http.Response转换为Post

    现在,我们将更新fetchPost函数以返回<Post>。为此,我们需要:

    1.将响应主体转换为带有dart包的jsonMap
    2.如果服务器返回状态码为200的"OK"响应,则使用fromJson工厂将jsonMap转换为Post
    3.如果服务器返回意外响应,则抛出错误

    Future<Post> fetchPost() async {
      final response =
          await http.get('https://jsonplaceholder.typicode.com/posts/1');
    
      if (response.statusCode == 200) {
        // If server returns an OK response, parse the JSON
        return Post.fromJson(json.decode(response.body));
      } else {
        // If that response was not OK, throw an error.
        throw Exception('Failed to load post');
      }
    }
    
    

    万岁!现在我们有了一个函数,我们可以调用它来从互联网上获取一篇文章!

    4. 使用Flutter展示数据

    为了使获取的数据可以在屏幕上显示,我们使用FutureBuilder控件。FutureBuilder 控件附带了Flutter,使得使用异步数据源变得容易。

    我们必须提供两个参数:
    1.在这个例子中,我们将调用Futrue中的fetchPost()函数

    1. 一个builder函数,告诉Flutter要呈现什么,这取决于Future的状态:加载、成功或错误。
    FutureBuilder<Post>(
      future: fetchPost(),
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          return Text(snapshot.data.title);
        } else if (snapshot.hasError) {
          return Text("${snapshot.error}");
        }
    
        // By default, show a loading spinner
        return CircularProgressIndicator();
      },
    );
    
    

    5.将获取调用移出“build()”方法

    尽管很方便,但是不建议在build()方法中调用API。

    每当Flutter想要更改视图中的任何内容时,它都会调用build()方法,而这种情况经常出人意料地发生。如果在`build()'方法中留下fetch调用,则API中将充斥着不必要的调用,并减慢应用程序的速度。

    以下是一些更好的选择,因此它只会在页面最初加载时命中API。

    将其传递到StatelessWidget

    使用这个策略,父小部件负责调用fetch方法,存储其结果,然后将其传递给小部件。

    class MyApp extends StatelessWidget {
      final Future<Post> post;
    
      MyApp({Key key, this.post}) : super(key: key);
    
    

    您可以在下面的完整示例中看到这个示例的工作示例。

    StatefulWidget状态的生命周期中调用它

    如果您的小部件是有状态的,您可以在initState'](https://docs.flutter.io/flutter/widgets/State/initState.html)或[didChangeDependencies'方法中调用获取方法。

    initstate被调用一次,然后再也不会调用。如果您想选择重新加载API以响应[inheritedWidget](https://docs.flutter.io/flutter/widgets/inheritedWidget class.html)更改,请将调用放入didchangeDependencies方法。更多详情请参见[state](https://docs.flutter.io/flutter/widgets/state class.html)。

    class _MyAppState extends State<MyApp> {
      Future<Post> post;
    
      @override
      void initState() {
        super.initState();
        post = fetchPost();
      }
    
    

    测试

    有关如何测试此功能的信息,请参阅以下文章:

    完整例子

    import 'dart:async';
    import 'dart:convert';
    
    import 'package:flutter/material.dart';
    import 'package:http/http.dart' as http;
    
    Future<Post> fetchPost() async {
      final response =
          await http.get('https://jsonplaceholder.typicode.com/posts/1');
    
      if (response.statusCode == 200) {
        // If the call to the server was successful, parse the JSON
        return Post.fromJson(json.decode(response.body));
      } else {
        // If that call was not successful, throw an error.
        throw Exception('Failed to load post');
      }
    }
    
    class Post {
      final int userId;
      final int id;
      final String title;
      final String body;
    
      Post({this.userId, this.id, this.title, this.body});
    
      factory Post.fromJson(Map<String, dynamic> json) {
        return Post(
          userId: json['userId'],
          id: json['id'],
          title: json['title'],
          body: json['body'],
        );
      }
    }
    
    void main() => runApp(MyApp(post: fetchPost()));
    
    class MyApp extends StatelessWidget {
      final Future<Post> post;
    
      MyApp({Key key, this.post}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Fetch Data Example',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: Scaffold(
            appBar: AppBar(
              title: Text('Fetch Data Example'),
            ),
            body: Center(
              child: FutureBuilder<Post>(
                future: post,
                builder: (context, snapshot) {
                  if (snapshot.hasData) {
                    return Text(snapshot.data.title);
                  } else if (snapshot.hasError) {
                    return Text("${snapshot.error}");
                  }
    
                  // By default, show a loading spinner
                  return CircularProgressIndicator();
                },
              ),
            ),
          ),
        );
      }
    }
    

    二、效果图

    三、原文链接

    1.Flutter初步探索(四)网络连接

    四、参考文档

    1.Fetch data from the internet

    五、公众号

    不器猿

    相关文章

      网友评论

        本文标题:Flutter初步探索(四)网络连接

        本文链接:https://www.haomeiwen.com/subject/dfrllqtx.html