現在要給公司開發一個內部使用的APP,但是因爲是小公司,沒有多餘的服務器資源,只能拿公司的主機當服務器,也只能在通過映射實現外網訪問。所以呀,很蛋疼,只能想辦法判斷用戶是在內網使用APP,還是在外網使用APP,然後根據環境選擇URL請求的IP地址。
首先是新建一個dart文件,把Flutter應用和頁面的架子搭起來,然後運行調試,確認應用可以正常跑起來。
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return new Scaffold(
);
}
}
雖然很容易發出網絡請求,但使用原始的Future <http.Response>並不是很方便。所以,爲了讓我們的開發更輕鬆一些,我們可以將http.Response轉換爲我們自己的Dart對象。
首先,我們需要創建一個ComeBack類,其中包含來自網絡請求的數據。它還將包含一個工廠構造函數,允許我們從json創建一個ComeBack。當然,手動轉換JSON只是一種選擇,還可以用JSON和序列化。
class ComeBack {
final int code;
final String msg;
final data;
ComeBack({
this.code,
this.msg,
this.data,
});
factory ComeBack.fromJson(Map<String, dynamic> json) {
return ComeBack(
code: json['code'],
msg: json['msg'],
data: json['data'],
);
}
}
給兩個固定的內網/外網地址,再定義一個全局變量來承載實際的請求地址。
final String urlExtranet = 'http://218.15.158.64:8001/';
final String urlIntranet = 'http://192.168.9.247/';
String url = '';
http.get方法返回包含Response的Future,Future是用於處理異步操作的核心Dart類,它用於表示將來某個時間可用的潛在值或錯誤信息。http.Response類包含從成功的http調用接收的數據。
如果對內網IP(urlIntranet
)的調用成功,則說明當前用戶處於內網環境,那麼接下來使用的都是內網IP。如果該調用不成功,則拋出錯誤,那麼就立即切換爲外網IP繼續訪問。
Future<ComeBack> fetchToken() async {
url = urlIntranet;
await http.get(url).catchError(
(error) {
url = urlExtranet;
}
);
final response = await http.post(
url + 'api/apirunner/auth/',
body: {'username': 'username', 'password': 'password'},
);
if (response.statusCode == 200) {
return ComeBack.fromJson(json.decode(response.body));
} else {
throw Exception('無法加載數據');
}
}
爲了獲取數據並將其顯示在屏幕上,我們可以使用FutureBuilder組件, FutureBuilder組件附帶Flutter,可以輕鬆使用異步數據源。
future參數表示我們希望使的Future,在我們的例子中,我們將調用我們的fetchToken()函數。
builder參數是一個構建器函數,它告訴Flutter要呈現什麼,具體取決於Future的狀態:加載中、請求成功或請求錯誤。
………
return new Scaffold(
body: FutureBuilder<ComeBack>(
future: fetchToken(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data.data);
} else if (snapshot.hasError) {
return Center(
child: SizedBox(
height: 92.0,
child: Column(
children: <Widget>[
Icon(
Icons.sentiment_very_dissatisfied,
size: 32.0,
),
Text('${snapshot.error}'),
],
),
),
);
}
return Center(
child: CircularProgressIndicator(),
);
},
),
);
………
如下,屏幕可以會出現三種狀態:加載中狀態、請求成功狀態和請求錯誤狀態,請求錯誤狀態會顯示錯誤信息。