FlutterFuture 与 FutureBuilder 异步编程代码示例 ( FutureBuilder 构造函数设置 | 处理 Flutter 中文乱码 | 完整代码示例 )
Posted 韩曙亮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FlutterFuture 与 FutureBuilder 异步编程代码示例 ( FutureBuilder 构造函数设置 | 处理 Flutter 中文乱码 | 完整代码示例 )相关的知识,希望对你有一定的参考价值。
一、FutureBuilder 简介
FutureBuilder 本质是组件 : FutureBuilder 构造好以后 , 会自动执行异步操作 , 并返回 Widget 组件 , 因此 FutureBuilder 也是一个组件 , 在不同的状态下显示不同样式的组件 ;
FutureBuilder 泛型设置 : FutureBuilder 的泛型 , 表示异步调用得到的 Future 的泛型 , 也就是返回结果的格式 ; FutureBuilder<CommonModel> 表示异步调用 Future 的返回值是 Future<CommonModel> ;
Future<T> future 参数设置 : 这是设置的是异步操作方法 , 下面的 httpGet() 方法 , 是一个返回 Future<CommonModel> 类型的方法 , 可以直接设置给 FutureBuilder 构造函数作为参数 ;
/// 调用 Http Get 方法 , 获取服务器的 json 数据
Future<CommonModel> httpGet() async {
//var url = Uri.parse('https://jsonplaceholder.typicode.com/posts/1');
var url = Uri.parse('https://www.devio.org/io/flutter_app/json/test_common_model.json');
// 异步请求 , 获取远程服务器信息
final response = await http.get(url);
/// 处理中文乱码
Utf8Decoder utf8decoder = Utf8Decoder();
/// 将二进制 Byte 数据以 UTF-8 格式编码 , 获取编码后的字符串
String responseString = utf8decoder.convert(response.bodyBytes);
// 将 json 字符串信息转为 Map<String, dynamic> 类型的键值对信息
Map<String, dynamic> jsonMap = json.decode(responseString);
return CommonModel.fromJson(jsonMap);
}
@required AsyncWidgetBuilder<T> builder 参数是必须设置的参数 , 该参数是 AsyncWidgetBuilder<T> 类型 的方法 :
typedef AsyncWidgetBuilder<T> = Widget Function(BuildContext context, AsyncSnapshot<T> snapshot);
传入的参数如下 : 自己写一个匿名函数 , 参数是 BuildContext context, AsyncSnapshot<T> snapshot , 返回值是 Widget ;
(BuildContext context, AsyncSnapshot<CommonModel> snapshot){
return Text("");
}
在上述 匿名函数 中 , 开始根据 AsyncSnapshot<CommonModel> snapshot 参数进行各种操作 , BuildContext context 参数在本次没有用到 ;
通过 snapshot.connectionState 可以获取当前异步请求的状态 , 可以在请求中显示进度条 , 请求后判定是否请求成功 , 如果出错 , 则显示报错信息 , 如果请求成功 , 则显示请求成功的信息 ;
无论怎样 , 最终要返回一个 Widget 组件 ;
FutureBuilder 构造函数完整代码示例 :
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("HTTP Get 请求"),
),
// 线性布局 列
body: FutureBuilder<CommonModel>(
// 设置异步调用的方法
future: httpGet(),
/// 接收如下类型的对象
/// typedef AsyncWidgetBuilder<T> = Widget Function(BuildContext context, AsyncSnapshot<T> snapshot);
builder: (BuildContext context, AsyncSnapshot<CommonModel> snapshot){
/// 判断 AsyncSnapshot 的连接状态
switch(snapshot.connectionState){
case ConnectionState.none:
return Text("未连接");
case ConnectionState.waiting:
/// 返回一个进度条
return Center(child: CircularProgressIndicator(),);
case ConnectionState.active:
/// 激活状态 , 返回一个进度条
return Text("");
case ConnectionState.done:
/// 请求结束 , 如果出现错误 , 则返回错误信息
/// 如果请求成功 , 返回从网络中请求的数据
if(snapshot.hasError) {
return Text("请求失败 , 报错信息 : ${snapshot.error}", style: TextStyle(color: Colors.red),);
} else {
return Text("请求成功 , 获取信息 : ${snapshot.data?.url}", style: TextStyle(color: Colors.green),);
}
}
},
),
),
);
}
二、处理 Flutter 中的中文乱码
数据是以 UTF-8 格式进行编码的 , 只能以 UTF-8 格式进行解码 ;
创建 Utf8Decoder 解码器 ,
/// 处理中文乱码
Utf8Decoder utf8decoder = Utf8Decoder();
调用解码器的 convert 方法 , 传入原始的二进制数据 , 注意是字节数组类型的数据 ;
/// 将二进制 Byte 数据以 UTF-8 格式编码 , 获取编码后的字符串
String responseString = utf8decoder.convert(response.bodyBytes);
得到的返回值就是编码正确的字符串文本信息 ;
完整代码示例 :
/// 调用 Http Get 方法 , 获取服务器的 json 数据
Future<CommonModel> httpGet() async {
//var url = Uri.parse('https://jsonplaceholder.typicode.com/posts/1');
var url = Uri.parse('https://www.devio.org/io/flutter_app/json/test_common_model.json');
// 异步请求 , 获取远程服务器信息
final response = await http.get(url);
/// 处理中文乱码
Utf8Decoder utf8decoder = Utf8Decoder();
/// 将二进制 Byte 数据以 UTF-8 格式编码 , 获取编码后的字符串
String responseString = utf8decoder.convert(response.bodyBytes);
// 将 json 字符串信息转为 Map<String, dynamic> 类型的键值对信息
Map<String, dynamic> jsonMap = json.decode(responseString);
return CommonModel.fromJson(jsonMap);
}
三、完整代码示例
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
/// json 序列化 , 反序列化 包
import 'dart:convert';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
/// HTTP GET 返回值
String httpGetResult = "";
/// 调用 Http Get 方法 , 获取服务器的 json 数据
Future<CommonModel> httpGet() async {
//var url = Uri.parse('https://jsonplaceholder.typicode.com/posts/1');
var url = Uri.parse('https://www.devio.org/io/flutter_app/json/test_common_model.json');
// 异步请求 , 获取远程服务器信息
final response = await http.get(url);
/// 处理中文乱码
Utf8Decoder utf8decoder = Utf8Decoder();
/// 将二进制 Byte 数据以 UTF-8 格式编码 , 获取编码后的字符串
String responseString = utf8decoder.convert(response.bodyBytes);
// 将 json 字符串信息转为 Map<String, dynamic> 类型的键值对信息
Map<String, dynamic> jsonMap = json.decode(responseString);
return CommonModel.fromJson(jsonMap);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("HTTP Get 请求"),
),
// 线性布局 列
body: FutureBuilder<CommonModel>(
// 设置异步调用的方法
future: httpGet(),
/// 接收如下类型的对象
/// typedef AsyncWidgetBuilder<T> = Widget Function(BuildContext context, AsyncSnapshot<T> snapshot);
builder: (BuildContext context, AsyncSnapshot<CommonModel> snapshot){
/// 判断 AsyncSnapshot 的连接状态
switch(snapshot.connectionState){
case ConnectionState.none:
return Text("未连接");
case ConnectionState.waiting:
/// 返回一个进度条
return Center(child: CircularProgressIndicator(),);
case ConnectionState.active:
/// 激活状态 , 返回一个进度条
return Text("");
case ConnectionState.done:
/// 请求结束 , 如果出现错误 , 则返回错误信息
/// 如果请求成功 , 返回从网络中请求的数据
if(snapshot.hasError) {
return Text("请求失败 , 报错信息 : ${snapshot.error}", style: TextStyle(color: Colors.red),);
} else {
return Text("请求成功 , 获取信息 : ${snapshot.data?.url}", style: TextStyle(color: Colors.green),);
}
}
},
),
),
);
}
}
class CommonModel {
final String? icon;
final String? title;
final String? url;
final String? statusBarColor;
final bool? hideAppBar;
CommonModel({this.icon, this.title, this.url, this.statusBarColor, this.hideAppBar});
factory CommonModel.fromJson(Map<String, dynamic> json) {
return CommonModel(
icon: json['icon'],
title: json['title'],
url: json['url'],
statusBarColor: json['statusBarColor'],
hideAppBar: json['hideAppBar'],
);
}
}
执行结果 :
四、相关资源
参考资料 :
- Flutter 官网 : https://flutter.dev/
- Flutter 插件下载地址 : https://pub.dev/packages
- Flutter 开发文档 : https://flutter.cn/docs ( 强烈推荐 )
- 官方 GitHub 地址 : https://github.com/flutter
- Flutter 中文社区 : https://flutter.cn/
- Flutter 实用教程 : https://flutter.cn/docs/cookbook
- Flutter CodeLab : https://codelabs.flutter-io.cn/
- Dart 中文文档 : https://dart.cn/
- Dart 开发者官网 : https://api.dart.dev/
- Flutter 中文网 : https://flutterchina.club/ , http://flutter.axuer.com/docs/
- Flutter 相关问题 : https://flutterchina.club/faq/ ( 入门阶段推荐看一遍 )
- GitHub 上的 Flutter 开源示例 : https://download.csdn.net/download/han1202012/15989510
- Flutter 实战电子书 : https://book.flutterchina.club/chapter1/
- Dart 语言练习网站 : https://dartpad.dartlang.org/
重要的专题 :
- Flutter 动画参考文档 : https://flutterchina.club/animations/
博客源码下载 :
-
GitHub 地址 : https://github.com/han1202012/flutter_http( 随博客进度一直更新 , 有可能没有本博客的源码 )
-
博客源码快照 : https://download.csdn.net/download/han1202012/21528472 ( 本篇博客的源码快照 , 可以找到本博客的源码 )
以上是关于FlutterFuture 与 FutureBuilder 异步编程代码示例 ( FutureBuilder 构造函数设置 | 处理 Flutter 中文乱码 | 完整代码示例 )的主要内容,如果未能解决你的问题,请参考以下文章
Flutter Future <String> 不能分配给参数类型字符串
如何使用 Flutter future<bool> 检查 Firestore 中是不是存在子集合
如何防止 FutureBuilder 的重建,即使其潜在的未来没有改变
FutureBuilder 中的 DocumentSnapshot:错误状态:无法获取 DocumentSnapshotPlatform 上不存在的字段