首先将依赖加上
1.巧妇难为无米之炊
首先我们需要找写测试的url链接,有一个好地方,那就是Github提供了很多api
但在此之前我们需要先行处理一些事,比如注册Github账号,获取一个token
下面的Github账号是我专门为Flutter准备的,token值就不加密了,大家不要乱玩。
1.1:如何获取token
小头像-->Settings-->Developer settings -->Personal access tokens-->Generate new token
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="//数据内容 } 复制代码
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); }); } 复制代码
注,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值" } 复制代码
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.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.5:用post提交一个issue
api:
https://api.github.com/repos/用户名/项目名/issues?access_token=token值
请求头:Content-Type=application/json
,可以要当前文件的sha值
{ "title": "一起来Flutter之旅吧", "body": "Flutter,大家感觉怎么样?应该不难吧!" } 复制代码
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就是以前写得界面稍微改装一下,这里代码就不贴了。
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.使用
这样用起来就和往常一样,只要传个名字就行了
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中是很方便的,一行搞定。
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( 复制代码
共同学习,写下你的评论
评论加载中...
作者其他优质文章