flutter多環境配置及 Dio 請求封裝最佳實踐


小夥伴,很高興能看到這篇文章,也許你是 flutter 大牛,也許你是小白,請耐心看完, 這是 flutter 多環境配置及 Dio 請求封裝的最佳實踐, 相信這也是全網最好的一篇 flutter 實踐文章, 適合大中小型項目, 相信一定會有所收穫

如果閱讀過程中讓你感到困惑,請按照文章步驟,創建對應文件,編寫代碼運行項目感受一下,相信這不會讓你失望的

flutter 多環境配置

所謂多環境是指 開發環境, 聯調環境, 測試環境, 演示環境, 生產環境等,當我們在各個環境之間切換時,勢必需要快速高效的解決方案, 多環境配置由此而生, 相信在看到這篇文章之前,也看過很多關於環境配置的博文,大多都是在項目中手動切換環境變量以達到環境切換目的(例如下圖), 雖然能解決問題但是總感覺有些low,下面讓我們來解開 flutter 正確的啓動方式
在這裏插入圖片描述

目錄結構概覽

先來看下圖的 目錄結構總覽, 接下來我們會逐一創建各個文件,並詳細講解其作用
==需要注意每個文件的位置==
  1. config.dart // 環境公共配置文件
  2. dev.dart // 開發環境配置文件
  3. prod.dart // 生產環境配置文件
  4. main.dart // 項目入口文件
  5. index.dart // 項目主頁文件
  6. http.dart // dio請求封裝文件
  7. interface.dart // 接口文件
    在這裏插入圖片描述

創建文件

  1. 在 lib 目錄下創建 public 文件夾

  2. 在public目錄下創建 config.dart 文件

  3. 在public目錄下創建 dev.dart 文件

  4. 在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();
    });
  }
}

啓動項目三種方式

  1. android studio 用戶
    通過配置啓動項 運行項目 (如何配置上面講過)
  2. vs code 用戶
    在launch文件中配置 路徑: lib/public/dev.dart 按 F5 啓動項目
  3. 命令行啓動
    進入項目目錄下 打開 cmd 輸入 如下命令 啓動項目
    flutter run -t lib/public/dev.dart
    

最後我們啓動項目看下效果吧

在這裏插入圖片描述

模板項目地址

有些小夥伴可能者編寫代碼時出錯了,這裏我放了自己的模板項目地址

鏈接: 模板項目地址.

結束語

到這裏我們所有的配置都已經完成了, 另外根據請求方法不同和後臺返回數據格式不同, 在 http.dart 文件中我只配置了
post 請求的, 只對我們公司的數據進行了格式處理, 簡單舉個列子,小夥伴們需要舉一反三,自己配置其他請求和數據格式化

如果這篇文章對你有幫助請支持下作者創作更多最佳實踐文章

支付寶

在這裏插入圖片描述

微信

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章