flutter多环境配置及 Dio 请求封装最佳实践
小伙伴,很高兴能看到这篇文章,也许你是 flutter 大牛,也许你是小白,请耐心看完, 这是 flutter 多环境配置及 Dio 请求封装的最佳实践, 相信这也是全网最好的一篇 flutter 实践文章, 适合大中小型项目, 相信一定会有所收获
如果阅读过程中让你感到困惑,请按照文章步骤,创建对应文件,编写代码运行项目感受一下,相信这不会让你失望的
flutter__4">flutter 多环境配置
所谓多环境是指 开发环境, 联调环境, 测试环境, 演示环境, 生产环境等,当我们在各个环境之间切换时,势必需要快速高效的解决方案, 多环境配置由此而生, 相信在看到这篇文章之前,也看过很多关于环境配置的博文,大多都是在项目中手动切换环境变量以达到环境切换目的(例如下图), 虽然能解决问题但是总感觉有些low,下面让我们来解开 flutter 正确的启动方式
**
flutter__9">提示: 在本地初始化一个 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__168">配置 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 请求的, 只对我们公司的数据进行了格式处理, 简单举个列子,小伙伴们需要举一反三,自己配置其他请求和数据格式化