首先咱們須要找寫測試的url連接,有一個好地方,那就是Github提供了不少api
但在此以前咱們須要先行處理一些事,好比註冊Github帳號,獲取一個token
下面的Github帳號是我專門爲Flutter準備的,token值就不加密了,你們不要亂玩。html
小頭像-->Settings-->Developer settings -->Personal access tokens-->Generate new token
node
api:
https://api.github.com/repos/用戶名/項目名/contents/文件路徑?access_token=token值
請求頭:Content-Type=application/json
,請求體以下,注意文件內容須要用base64
能夠用wanandroid裏的工具轉化,該請求的其餘參數能夠詳見Github的相應apiandroid
{
"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"));
git
api:
https://api.github.com/repos/用戶名/項目名/contents/文件路徑?access_token=token值
請求頭:Content-Type=application/json
,請求體以下,注意文件內容須要用base64
關於sha值,在添加的時候,響應體中有,見上圖。每次修改也會返回新的sha值github
{
"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);
});
}
複製代碼
api:
https://api.github.com/repos/用戶名/項目名/contents/文件路徑?access_token=token值
請求頭:Content-Type=application/json
,能夠要當前文件的sha值json
{
"message": "delete by toly ",//提交信息
"sha":"文件所對應的sha值"
}
複製代碼
http庫的delete請求竟然不能加請求體?!這裏用PostMan演示一下後端
api:
https://api.github.com/repos/用戶名/項目名/issues?access_token=token值
請求頭:Content-Type=application/json
,能夠要當前文件的sha值api
{
"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);
});
}
複製代碼
api:
https://api.github.com/repos/用戶名/項目名/issues/第幾個?access_token=token值
bash
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的幾種經常使用的請求方式基本都會了吧。服務器
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"];
}
}
複製代碼
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"
}
複製代碼
你也能夠一點一點寫出這個實體類,不過推薦用生成的方法,比較有時候字段太多,比較費勁
這裏給一個用起來還不錯的地方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'];
}
複製代碼
如今徹底能夠將之前寫的界面改一改,而後用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);
});
}
複製代碼
你會發現上面雖然能用,可是看着真的很是難受,怎麼讓它用起來爽一點呢,兩個字封裝
實現一個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複用的爽感。
這樣用起來就和往常同樣,只要傳個名字就好了
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);
}
複製代碼
dio做爲JoJo的奇妙冒險的幾部大boss,聽名字就挺霸氣,在網頁搜dio根本沒有Flutter的事
上來講的那個http包相對比較原始,dio封裝的更好些,用法比較多。
反正再怎麼玩,都脫離不了http請求,因此要分清主次,切莫捨本逐末。
dependencies:
dio: ^2.1.13
複製代碼
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));
複製代碼
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);
});
}
複製代碼
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);
});
}
複製代碼
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);
});
}
複製代碼
就拿掘金的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);
});
複製代碼
文件上傳一直是個較難問題,要實現文件上傳,你須要一點後端的知識
核心就是客戶端將數據經過請求給服務器,服務器將請求中的內容進行操做
上傳也就是服務器將數據或文件存儲到了服務端指定位置。
通常經過表單提交,也能夠直接將二進制流經過請求體給服務端。
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){//將表單經過請求體傳給服務端
});
複製代碼
看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( 複製代碼
關於更多dio的用法,這裏不過多介紹,能夠去這裏看一下,dio做者的講解
本文到此接近尾聲了,若是想快速嚐鮮Flutter,《Flutter七日》會是你的必備佳品;若是想細細探究它,那就跟隨個人腳步,完成一次Flutter之旅。
另外本人有一個Flutter微信交流羣,歡迎小夥伴加入,共同探討Flutter的問題,本人微信號:zdl1994328
,期待與你的交流與切磋。