flutter 多環境配置及Dio請求封裝最佳實踐
小夥伴,很高興能看到這篇文章,也許你是 flutter 大牛,也許你是小白,請耐心看完, 這是 flutter 多環境配置及 Dio 請求封裝的最佳實踐, 相信這也是全網最好的一篇 flutter 實踐文章, 適合大中小型項目, 相信一定會有所收穫
如果閱讀過程中讓你感到困惑,請按照文章步驟,創建對應文件,編寫代碼運行項目感受一下,相信這不會讓你失望的
flutter 多環境配置
所謂多環境是指 開發環境, 聯調環境, 測試環境, 演示環境, 生產環境等,當我們在各個環境之間切換時,勢必需要快速高效的解決方案, 多環境配置由此而生, 相信在看到這篇文章之前,也看過很多關於環境配置的博文,大多都是在項目中手動切換環境變量以達到環境切換目的(例如下圖), 雖然能解決問題但是總感覺有些low,下面讓我們來解開 flutter 正確的啓動方式
目錄結構概覽
先來看下圖的 目錄結構總覽, 接下來我們會逐一創建各個文件,並詳細講解其作用
==需要注意每個文件的位置==
- config.dart // 環境公共配置文件
- dev.dart // 開發環境配置文件
- prod.dart // 生產環境配置文件
- main.dart // 項目入口文件
- index.dart // 項目主頁文件
- http.dart // dio請求封裝文件
- interface.dart // 接口文件
創建文件
-
在 lib 目錄下創建 public 文件夾
-
在public目錄下創建 config.dart 文件
-
在public目錄下創建 dev.dart 文件
-
在public目錄下創建 prod.dart 文件
目前先創建這幾個文件
環境變量公共配置文件 config.dart
打開 config.dart 文件 編寫如下代碼 推薦使用 android studio 編寫 flutter 應用
/// 注意這裏包的引入路徑
/// 如果你是 Android studio 用戶 這裏可以不着急引入包,當你把代碼複製到自己的項目裏時,由於路徑不對,
/// 編輯器檢測不到對應的包時,對應的代碼會變紅,如下圖,此時把選中紅色波浪線的單詞按住 ctrl + enter鍵 選擇需要的包就好了
import 'package:flutter/material.dart';
/**
* @CreateDate: 2020/7/2 20:45
* @Author: Gleason
* @Description: 環境變量
**/
/// 這裏繼承自 InheritedWidget 這個類
/// 可以在 weiget 中通過上下文獲取到環境變量
/// 當然 也可把 主題和一些全局 設置放到這裏
class ENV extends InheritedWidget {
static String appName; // 系統名稱
static String envName; // 運行環境
static String baseUrl; // 基礎url
ENV({
@required String appName,
@required String envName,
@required String baseUrl,
@required Widget child,
}) : super(child: child){
ENV.appName = appName;
ENV.envName = envName;
ENV.baseUrl = baseUrl;
}
// 這裏 是在 weiget 中拿到當前環境變量的關鍵
static ENV of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType(aspect: ENV);
}
@override
bool updateShouldNotify(InheritedWidget oldWidget) => false;
}
配置 dev 環境 (開發環境)
import 'package:flutter_template/main.dart';
import 'package:flutter/material.dart';
import 'package:flutter_template/public/config.dart';
void main() {
var configuredApp = new ENV(
appName: 'app 名稱', // 項目名稱 或者 app 名稱
envName: 'dev', // 環境變量
baseUrl: 'https://www.dev.com/', // 接口基礎地址
child: new MyApp(),
);
runApp(configuredApp);
}
配置 prod 壞境(生產環境)
import 'package:flutter_template/main.dart';
import 'package:flutter/material.dart';
import 'package:flutter_template/public/config.dart';
void main() {
var configuredApp = new ENV(
appName: 'app 名稱', // 項目名稱 或者 app 名稱
envName: 'prod',// 環境變量
baseUrl: 'https://www.prod.com/', // 接口基礎地址
child: new MyApp(),
);
runApp(configuredApp);
}
調整項目入口文件 main.dart
如果不知道 main.dart 文件那來的 請看開篇 項目結構概覽
因爲 main.dart 作爲項目入口文件 所以我們要把項目首頁進行遷移到 index.dart 做下功能文件區分
/// 項目入口文件
import 'package:flutter/material.dart';
import 'package:flutter_template/index.dart';
import 'package:flutter_template/public/config.dart';
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 在任何地方調用AppConfig.of(context)以獲取特定於環境的配置
var config = ENV.of(context);
print('config$config')
return new MaterialApp(
title: ENV.appName,
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new HomePage(), //這裏將引入 index.dart 中的 homepage weiget
);
}
}
設置項目主頁 index.dart
import 'package:flutter/material.dart';
/// 這裏需要引入 環境變量配置
import 'package:flutter_template/public/config.dart';
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => new _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(ENV.appName),
),
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
/// 通過 ENV 環境變量可以拿到我們配置的環境信息
child: Text('app 名稱: ${ENV.envName}.'),
padding: EdgeInsets.all(15.0),
),
Container(
child: Text('baseUrl: ${ENV.baseUrl}.'),
padding: EdgeInsets.all(15.0),
),
],
),
),
);
}
}
配置 android studio 啓動命令
按照圖示選擇 Edit configur… 選項, 接下來按照 下面圖片跟着配置就可以了,如果不知道我在幹啥,就先跟着做,一會配置完就懂了
可以按着下圖片中第二步往下做, 第一步已經在 上圖中完成了
重複上述操作,照此方式配置 prod 測試, 演示, 聯調環境吧
封裝 Dio 請求
接下來我們封裝的 dio 請求, 要和之前的環境配置關聯上這樣纔是一個整體, 跟着往下操作吧
創建 http.dart 文件
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:flutter_template/public/config.dart';
/// dio 初始化設置
final dio = Dio(BaseOptions(
baseUrl: ENV.baseUrl, // 如果你啓動的是 dev 那麼這裏的 baseUrl = https://www.dev.com/
connectTimeout: 5000, // 配置請求超時
receiveTimeout: 100000,
contentType:"application/json; charset=utf-8", // 設置content-type
));
/// 接口封裝
/// 說到這裏我們先來講下接口構成
/// 接口 = 基礎路徑 + 接口地址 也就是 interface = baseUrl + path
/// 比如說登錄接口 http://www.dev.com/login
/// 這個登錄接口的構成 由 baseUtl(http://www.dev.com/) 和 path(login) 組成
/// baseUrl 我們在環境變量 設置過(dev 和 prod文件裏的baseUrl)
/// path 是我們在後端提供的接口文檔中獲得的
/// 下面
/// main 方法中的參數 url 只需傳 login 即可
/// main 方法中 type 是請求類型 如get/post/delete/put ....
/// body 是請求帶參
Future main({String url = '', String type = "get", dynamic body}) async {
type = type.toUpperCase();
print('請求參數: url:$url,type:$type,body:$body');
if (type == 'POST') {
// await dio.(url).then((value) => value).catchError((e)=>e);
Response response = await dio.post(url,data: body);
return response.data;
}
}
創建 interface.dart 文件 (接口註冊)
import 'package:flutter_template/public/http.dart';
class Fetch {
/// login 接口
static login(body)=> main(url: 'login',type: 'post', body:body);
/// 註冊 接口
static register(body)=> main(url: 'register',type: 'post', body:body);
/// 把項目中用到 所有接口都寫在這裏 接口統一管理
/// 如果接口名稱改動了 只需要 修改 url 參數即可,項目裏用到該接口的地方就不需要修改了
/// 小夥伴是不是覺得 這纔是 flutter 最佳實踐
}
調用接口 更新 index.dart 文件
接下來我們要結合上邊所有配置 調用我們配置好的接口了
import 'package:flutter/material.dart';
import 'package:flutter_template/public/config.dart';
import 'package:flutter_template/public/interface.dart';
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => new _HomePageState();
}
class _HomePageState extends State<HomePage> {
/// 接收 調用接口返回數據變量
String data;
/// 組件初始化時 調用接口
@override
void initState() {
loadData();
super.initState();
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(ENV.appName),
),
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
child: Text('app 名稱: ${ENV.envName}.'),
padding: EdgeInsets.all(15.0),
),
Container(
child: Text('當前環境: ${ENV.baseUrl}.'),
padding: EdgeInsets.all(15.0),
),
Container(
child: Text('響應數據: \n$data.'),
padding: EdgeInsets.all(15.0),
),
],
),
),
);
}
/// 調用接口方法
void loadData() async {
Map result =
await Fetch.login({'userid': 'bianliuzhu', 'password': 'bianliuzhu'});
print('result:${result}');
/// 更新數據
setState(() {
data = result['user'].toString();
});
}
}
啓動項目三種方式
- android studio 用戶
通過配置啓動項 運行項目 (如何配置上面講過) - vs code 用戶
在launch文件中配置 路徑: lib/public/dev.dart 按 F5 啓動項目 - 命令行啓動
進入項目目錄下 打開 cmd 輸入 如下命令 啓動項目flutter run -t lib/public/dev.dart
最後我們啓動項目看下效果吧
模板項目地址
有些小夥伴可能者編寫代碼時出錯了,這裏我放了自己的模板項目地址
鏈接: 模板項目地址.
結束語
到這裏我們所有的配置都已經完成了, 另外根據請求方法不同和後臺返回數據格式不同, 在 http.dart 文件中我只配置了
post 請求的, 只對我們公司的數據進行了格式處理, 簡單舉個列子,小夥伴們需要舉一反三,自己配置其他請求和數據格式化