继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

[Flutter必备]-Flutter中的网络访问

张风捷特烈
关注TA
已关注
手记 72
粉丝 21
获赞 56
首先将依赖加上


1



1.巧妇难为无米之炊

首先我们需要找写测试的url链接,有一个好地方,那就是Github提供了很多api
但在此之前我们需要先行处理一些事,比如注册Github账号,获取一个token
下面的Github账号是我专门为Flutter准备的,token值就不加密了,大家不要乱玩。


1.1:如何获取token

小头像-->Settings-->Developer settings -->Personal access tokens-->Generate new token


1



1.2:如何通过post请求在你的github项目中添加一个文件

api:https://api.github.com/repos/用户名/项目名/contents/文件路径?access_token=token值
请求头:Content-Type=application/json,请求体如下,注意文件内容需要用base64
可以用wanandroid里的工具转化,该请求的其他参数可以详见Github的相应api

{   "message": "commit from toly ",//提交信息   "content": "aGVsbG8="//数据内容 } 复制代码


1


  • Flutter中发送put请求,在github项目中添加一个文件

import 'package:http/http.dart' as client; main() {   put(); } void put() {   var baseUrl="https://api.github.com/";   var operate="repos/toly-flutter/flutter_journey/contents/";   var path="http-put-file.txt";   var params="?access_token=4514388836f6da9f6c6cf7ba0721f2a6d1e89528";//请求参数   var api =baseUrl+operate+path+params;//url   Map<String ,String> headers = {"Content-Type":"application/json"};//请求头   var reqBody="""   {   "message": "commit from commit from toly",   "content": "aGVsbG8="   }   """;//请求体   client.put(api,headers:headers,body: reqBody).then((rep){     print(rep.statusCode);     print(rep.body);   }); } 复制代码


1


注,Dart中将字符串转换base64可以:base64Encode(utf8.encode("hello"));


1.3:通过put请求修改一个github文件

api:https://api.github.com/repos/用户名/项目名/contents/文件路径?access_token=token值
请求头:Content-Type=application/json,请求体如下,注意文件内容需要用base64
关于sha值,在添加的时候,响应体中有,见上图。每次修改也会返回新的sha值

{   "message": "update by toly ",//提交信息   "content": "aGVsbG8="//数据内容   "sha":"文件所对应的sha值" } 复制代码


1


  • Flutter中发送put请求,在github项目中修改一个文件

void update() {   var baseUrl="https://api.github.com/";   var operate="repos/toly-flutter/flutter_journey/contents/";   var path="http-put-file.txt";   var params="?access_token=4514388836f6da9f6c6cf7ba0721f2a6d1e89528";//请求参数   var api =baseUrl+operate+path+params;//url   Map<String ,String> headers = {"Content-Type":"application/json"};//请求头   var reqBody="""   {   "message": "update by toly",   "content": "5byg6aOO5o2354m554OI",   "sha":"b6fc4c620b67d95f953a5c1c1230aaab5db5a1b0"   }   """;//请求体   client.put(api,headers:headers,body: reqBody).then((rep){     print(rep.statusCode);     print(rep.body);   }); } 复制代码


1



1.4:通过delete请求删除一个github文件

api:https://api.github.com/repos/用户名/项目名/contents/文件路径?access_token=token值
请求头:Content-Type=application/json,可以要当前文件的sha值

{   "message": "delete by toly ",//提交信息   "sha":"文件所对应的sha值" } 复制代码

http库的delete请求居然不能加请求体?!这里用PostMan演示一下


1



1.5:用post提交一个issue

api:https://api.github.com/repos/用户名/项目名/issues?access_token=token值
请求头:Content-Type=application/json,可以要当前文件的sha值

{   "title": "一起来Flutter之旅吧",   "body": "Flutter,大家感觉怎么样?应该不难吧!" } 复制代码


1


  • Flutter中发送post请求,在github项目中添加一条issue

void post() {   var baseUrl="https://api.github.com/";   var operate="repos/toly-flutter/flutter_journey/issues";   var params="?access_token=4514388836f6da9f6c6cf7ba0721f2a6d1e89528";//请求参数   var api =baseUrl+operate+params;//url   Map<String ,String> headers = {"Content-Type":"application/json"};//请求头   var reqBody=""" {   "title": "一起来Flutter之旅吧",   "body": "Flutter,大家感觉怎么样?应该不难吧!" }   """;//请求体   client.post(api,headers:headers,body: reqBody).then((rep){     print(rep.statusCode);     print(rep.body);   }); } 复制代码

1.6:使用get请求获取一个issue

api:https://api.github.com/repos/用户名/项目名/issues/第几个?access_token=token值

void get(){   //GET /repos/:owner/:repo/issues/:issue_number   var baseUrl="https://api.github.com/";   var operate="repos/toly-flutter/flutter_journey/issues/1";   var params="?access_token=4514388836f6da9f6c6cf7ba0721f2a6d1e89528";//请求参数   var api =baseUrl+operate+params;//url   client.get(api).then((rep){     print(rep.statusCode);     print(rep.body);   }); } 复制代码

好了,Http的几种常用的请求方式基本都会了吧。


2. Json的解析

2.0:简介

Dart中的Map<String,String>对象和Json非常相似,所以可以用其作为转换媒介
通过convert包中的json.decode方法,可以将Json字符串转化成一个Map对象
在实体类中可以根据这个Map对象的属性对实体类进行实例化。

import 'dart:convert'; main() {   String jsonStr = """ {   "name":"Flutter之旅",   "author":"张风捷特烈" } """;   var book = Book.fromMap(json.decode(jsonStr));   print(book.name);//Flutter之旅   print(book.author);//张风捷特烈 } class Book {   String name;   String author;   Book.fromMap(Map<String, dynamic> json) {//根据Map穿件实例     name = json["name"];     author = json["author"];   } } 复制代码

2.1: 获取json

Github的https://api.github.com/users/用户名可以获取用户基本信息
这里就先解析我的https://api.github.com/users/toly1994328

{   "login": "toly1994328",   "id": 26687012,   "node_id": "MDQ6VXNlcjI2Njg3MDEy",   "avatar_url": "https://avatars3.githubusercontent.com/u/26687012?v=4",   "gravatar_id": "",   "url": "https://api.github.com/users/toly1994328",   "html_url": "https://github.com/toly1994328",   "followers_url": "https://api.github.com/users/toly1994328/followers",   "following_url": "https://api.github.com/users/toly1994328/following{/other_user}",   "gists_url": "https://api.github.com/users/toly1994328/gists{/gist_id}",   "starred_url": "https://api.github.com/users/toly1994328/starred{/owner}{/repo}",   "subscriptions_url": "https://api.github.com/users/toly1994328/subscriptions",   "organizations_url": "https://api.github.com/users/toly1994328/orgs",   "repos_url": "https://api.github.com/users/toly1994328/repos",   "events_url": "https://api.github.com/users/toly1994328/events{/privacy}",   "received_events_url": "https://api.github.com/users/toly1994328/received_events",   "type": "User",   "site_admin": false,   "name": "张风捷特烈(toly)",   "company": "捷特王国",   "blog": "http://www.toly1994.com",   "location": "China",   "email": null,   "hireable": null,   "bio": "The king of coder.",   "public_repos": 64,   "public_gists": 0,   "followers": 238,   "following": 9,   "created_at": "2017-03-26T09:55:25Z",   "updated_at": "2019-07-15T08:05:52Z" } 复制代码

2.2:实体类的生成

你也可以一点一点写出这个实体类,不过推荐用生成的方法,比较有时候字段太多,比较费劲
这里给一个用起来还不错的地方JSON to Dart,有时间自己写个转换插件来玩玩

class User {   String login;   int id;   String nodeId;   String avatarUrl;   String gravatarId;   String url;   String htmlUrl;   String followersUrl;   String followingUrl;   String gistsUrl;   String starredUrl;   String subscriptionsUrl;   String organizationsUrl;   String reposUrl;   String eventsUrl;   String receivedEventsUrl;   String type;   bool siteAdmin;   String name;   String company;   String blog;   String location;   String email;   String hireable;   String bio;   int publicRepos;   int publicGists;   int followers;   int following;   String createdAt;   String updatedAt;   User.fromJson(Map<String, dynamic> json) {     login = json['login'];     id = json['id'];     nodeId = json['node_id'];     avatarUrl = json['avatar_url'];     gravatarId = json['gravatar_id'];     url = json['url'];     htmlUrl = json['html_url'];     followersUrl = json['followers_url'];     followingUrl = json['following_url'];     gistsUrl = json['gists_url'];     starredUrl = json['starred_url'];     subscriptionsUrl = json['subscriptions_url'];     organizationsUrl = json['organizations_url'];     reposUrl = json['repos_url'];     eventsUrl = json['events_url'];     receivedEventsUrl = json['received_events_url'];     type = json['type'];     siteAdmin = json['site_admin'];     name = json['name'];     company = json['company'];     blog = json['blog'];     location = json['location'];     email = json['email'];     hireable = json['hireable'];     bio = json['bio'];     publicRepos = json['public_repos'];     publicGists = json['public_gists'];     followers = json['followers'];     following = json['following'];     createdAt = json['created_at'];     updatedAt = json['updated_at'];   } 复制代码

2.3.网络请求+json的使用

现在完全可以将以前写的界面改一改,然后用Github获取的数据填充进去
这里只是简单展示一下,说明网络数据和布局界面的对接,并没有做得太精细
GithubPanel就是以前写得界面稍微改装一下,这里代码就不贴了。


1



1


import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as client; import 'day6/github_panel.dart'; import 'day6/user.dart'; void main() {   var baseUrl = "https://api.github.com/";   var operate = "users/";   var name = "toly1994328";   var api = baseUrl + operate + name; //url   client.get(api).then((rep) {     var user = User.fromJson(json.decode(rep.body)); print(user.avatarUrl);     var scaffold = Scaffold(         appBar: AppBar(title: Text("Flutter之旅"),),         body: GithubPanel(user: user,)     );     var app = MaterialApp(       title: 'Flutter Demo',       theme: ThemeData(         primarySwatch: Colors.blue,       ),       home: scaffold,     );     return runApp(app);   }); } 复制代码

2.4.组件的再封装

你会发现上面虽然能用,但是看着真的非常难受,怎么让它用起来爽一点呢,两个字封装
实现一个GithubUserPanel,用法是传入一个用户名参数就行了。并且复用以前的面板。
由于网络访问是异步的,我们需要一个有状态的组件,当异步加载完成之后,再setState重新渲染。

import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as client; import 'github_panel.dart'; import 'user.dart'; class GithubUserPanel extends StatefulWidget {   GithubUserPanel({     Key key,     this.userName,   }) : super(key: key);   final String userName;   @override   _GithubUserPanelState createState() => _GithubUserPanelState(); } class _GithubUserPanelState extends State<GithubUserPanel> {   var baseUrl = "https://api.github.com/";   var operate = "users/";   var panel;   @override   void initState() {     super.initState();     var api = baseUrl + operate + widget.userName; //url     client.get(api).then((rep) {       var user = User.fromJson(json.decode(rep.body));       panel = GithubPanel(         user: user,       );       setState(() {});     });   }   @override   Widget build(BuildContext context) {     return Container(       child: panel,     );   } } 复制代码

也就这写代码就行了,是不是感受到了GithubPanel复用的爽感。


2.5.使用

这样用起来就和往常一样,只要传个名字就行了


1


void main() {     var scaffold = Scaffold(         appBar: AppBar(title: Text("Flutter之旅"),),         body: GithubUserPanel(userName: "toly1994328",)     );     var app = MaterialApp(       title: 'Flutter Demo',       theme: ThemeData(         primarySwatch: Colors.blue,       ),       home: scaffold,     );     return runApp(app); } 复制代码

3.网络请求包dio的使用

dio作为JoJo的奇妙冒险的几部大boss,听名字就挺霸气,在网页搜dio根本没有Flutter的事
上来说的那个http包相对比较原始,dio封装的更好些,用法比较多。
反正再怎么玩,都脱离不了http请求,所以要分清主次,切莫舍本逐末。

dependencies:   dio: ^2.1.13 复制代码

3.1:get获取github用户信息
var dio=Dio(); var baseUrl = "https://api.github.com/"; var operate = "users/"; var api=baseUrl+operate+"toly1994328"; dio.get(api).then((rep)=>print(rep.data)); 复制代码

3.2: put请求添加github项目文件
void put() {   var baseUrl="https://api.github.com/";   var operate="repos/toly-flutter/flutter_journey/contents/";   var path="http-put-file-dio.txt";   var params="?access_token=4514388836f6da9f6c6cf7ba0721f2a6d1e89528";//请求参数   var api =baseUrl+operate+path+params;//url   Map<String ,String> headers = {"Content-Type":"application/json"};//请求头   var reqBody="""   {   "message": "commit from commit from toly",   "content": "aGVsbG8="   }   """;//请求体   Dio().put(api,queryParameters:headers,data: reqBody).then((rep){     print(rep.statusCode);     print(rep.data);   }); } 复制代码

3.3:delete请求删除github项目文件

dio中的delete是可以添加请求体的

void delete() {   var baseUrl="https://api.github.com/";   var operate="repos/toly-flutter/flutter_journey/contents/";   var path="http-put-file-dio.txt";   var params="?access_token=4514388836f6da9f6c6cf7ba0721f2a6d1e89528";//请求参数   var api =baseUrl+operate+path+params;//url   Map<String ,String> headers = {"Content-Type":"application/json"};   var reqBody="""   {   "message": "delete by toly",   "sha": "b6fc4c620b67d95f953a5c1c1230aaab5db5a1b0"   }   """;   Dio().delete(api,queryParameters:headers,data: reqBody).then((rep){     print(rep.data);   }); } 复制代码

3.4:post提交一条issue
void post() {   var baseUrl="https://api.github.com/";   var operate="repos/toly-flutter/flutter_journey/issues";   var params="?access_token=4514388836f6da9f6c6cf7ba0721f2a6d1e89528";//请求参数   var api =baseUrl+operate+params;//url   Map<String ,String> headers = {"Content-Type":"application/json"};//请求头   var reqBody=""" {   "title": "张风捷特烈",   "body": "我是谁,我在哪里,我要到哪去?" }   """;//请求体   Dio().post(api,queryParameters:headers,data: reqBody).then((rep){     print(rep.statusCode);     print(rep.data);   }); } 复制代码

3.5:通过dio下载

就拿掘金的app下载吧,在dio中是很方便的,一行搞定。


1


var url="https://landing.juejin.im/app-download?utm_source=app_download&utm_medium=yingyongbao&utm_campaign=app1808"; Dio().download(url,"./掘金.apk").then((rep){   print(rep.statusCode);   print(rep.data); }); 复制代码

3.6:通过dio上传

文件上传一直是个较难问题,要实现文件上传,你需要一点后端的知识
核心就是客户端将数据通过请求给服务器,服务器将请求中的内容进行操作
上传也就是服务器将数据或文件存储到了服务端指定位置。
一般通过表单提交,也可以直接将二进制流通过请求体给服务端。

FormData formData = FormData.from({//创建表单   "name": "toly",   "age": 25,   "data":  UploadFileInfo(File("./data.json"), "data.json"),   "image":  UploadFileInfo(File("./photo.png"), "photo.png"), }); var api="/loadFile"; Dio().post(api, data: formData).then((rep){//将表单通过请求体传给服务端 }); 复制代码

3.7:基本配置参数

看Dio的源码中有一个可选参数BaseOptions

---->[dio-2.1.13/lib/src/dio.dart:53]---- class Dio {   /// Create Dio instance with default [Options].   /// It's mostly just one Dio instance in your application.   Dio([BaseOptions options]) { ---->[dio-2.1.13/lib/src/options.dart:39]---- class BaseOptions extends _RequestConfig {   BaseOptions({     String method,//请求方法     int connectTimeout,//链接超时     int receiveTimeout,//接收超时     Iterable<Cookie> cookies,//cookies     this.baseUrl,//基础Url     this.queryParameters,//请求参数     Map<String, dynamic> extra,     Map<String, dynamic> headers,//请求头     ResponseType responseType = ResponseType.json,//返回类型     ContentType contentType,//内容类型     ValidateStatus validateStatus,     bool receiveDataWhenStatusError = true,     bool followRedirects = true,     int maxRedirects = 5,    RequestEncoder requestEncoder,     ResponseDecoder responseDecoder,   }) : super( 复制代码




打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP