线上flutter 接口请求基本架构(线上实际项目搭建 不多讲直接上代码)2021年3月份整体更新
首先添加库: pubspec.yaml 目录下:
Flutter version 2.0.1
Dart version 2.12.0
dependencies:
retrofit: any
logger: any #for logging purpose
rxdart: ^0.26.0
json_annotation: 4.0.0# json 转换
shared_preferences: ^2.0.4 # 信息存储
package_info: ^2.0.0 # app信息
dev_dependencies:
retrofit_generator: any
build_runner: any
json_serializable: 4.0.3
接口请求工具类:dio基类
import 'package:dio/adapter.dart';
import 'package:dio/dio.dart';
import 'package:flutter_app/common/sharedPreferences/FastData.dart';
import 'package:package_info/package_info.dart';
import 'dart:io';
class Api {
Dio _dio;
String PEM="XXXXX"; // certificate content
String PKCS12File="XXXXX"; // certificate content
//dio 基本方法
Future<Dio> getDio() async {
var options = new BaseOptions(
connectTimeout: 5000,
receiveTimeout: 3000,
);
_dio = new Dio(options);
_dio.interceptors.add(AuthInterceptor()); // 添加 token
_dio.interceptors
.add(LogInterceptor(responseBody: true, requestBody: true)); //添加日志
//添加https证书 setHttpsPEM(),etHttpsPKCS12()
// 使用代理 setFindProxy()
return _dio;
}
//添加证书
setHttpsPEM() async{
(_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client) {
client.badCertificateCallback=(X509Certificate cert, String host, int port){
if(cert.pem==PEM){ // Verify the certificate
return true;
}
return false;
};
};
}
setHttpsPKCS12() async{
(_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client) {
SecurityContext sc = new SecurityContext();
//file is the path of certificate
sc.setTrustedCertificates(PKCS12File);
HttpClient httpClient = new HttpClient(context: sc);
return httpClient;
};
}
//设置代理
setFindProxy() async{
(_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client) {
// config the http client
client.findProxy = (uri) {
//proxy all request to localhost:8888
return "PROXY localhost:8888";
};
// you can also create a new HttpClient to dio
// return new HttpClient();
};
}
}
/*
*
*AuthInterceptor
*添加header认证
* */
class AuthInterceptor extends Interceptor {
String PLATFORM = "android"; //可根据代码进行判断
@override
onRequest(RequestOptions options) async {
//获取app版本
PackageInfo packageInfo = await PackageInfo.fromPlatform();
String version = packageInfo.version;
if (Platform.isIOS) {
PLATFORM = "ios";
} else if (Platform.isAndroid) {
PLATFORM = "android";
} else if (Platform.isWindows) {
PLATFORM = "Windows";
} else if (Platform.isMacOS) {
PLATFORM = "macos";
} else if (Platform.isLinux) {
PLATFORM = "Linux";
}
Map<String, String> headers = new Map();
headers["Accept-Charset"] = "utf-8";
headers["Connection"] = "keep-alive";
headers["Accept"] = "*/*";
headers["x-version"] = version; //自己更改配置
headers["x-platform"] = PLATFORM;
//获取存储数据 保存header token
String token = await FastData().getToken();
if (null!=token&&token.isNotEmpty) {
headers["Authorization"] = token; //添加自己项目中的请求头 进行保存
}
options.headers = headers;
return super.onRequest(options);
}
}
设置请求类型(post get 可自己添加想要的类型)
import 'package:flutter_app/ui/bean/LoginBean.dart';
import 'package:retrofit/retrofit.dart';
import 'package:dio/dio.dart';
part 'ApiService.g.dart';
@RestApi(baseUrl: "https://tapi.tticar.com/ttmall/")
abstract class ApiService {
factory ApiService(Dio dio, {String baseUrl}) => _ApiService(dio);
//登陆
@POST("/login")
@Header("Authorization bearer 39c1a1fa-26aa-404b-9756-e4547112cd65")
Future<LoginBean> getLogin(@Field('clientId') String clientId,@Field('clientSecret') String clientSecret,
@Field('username') String username,@Field('password') String password);
}
登录解析的bean
import 'package:json_annotation/json_annotation.dart';
part 'LoginBean.g.dart';
@JsonSerializable()
class LoginBean {
int code;
String message;
LoginBean({this.code, this.message});
factory LoginBean.fromJson(Map<String, dynamic> json) =>
_$LoginBeanFromJson(json);
Map<String, dynamic> toJson() => _$LoginBeanToJson(this);
}
数据存储
class FastData{
//token
String TOKEN="APP:TOKEN";
String USER_NAME="APP:USER:NAME";
//token
setToken(String token) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setString(TOKEN, token);
}
Future<String> getToken() async{
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getString(TOKEN);
}
//用户名
setUserName(String userName) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setString(USER_NAME, userName);
}
Future<String> getUserName() async{
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getString(USER_NAME);
}
}
请求接口 这个用到了 rxdart Stream.value()
Dio dio = await Api().getDio();
var apiService = ApiService(dio);
var logger = Logger(); //log打印
//请求接口
var stream = Stream.value(apiService.getLogin("TTMALL_APP", "123456", "13041203376", "jia321.."));
stream.listen((event) async{
//接口请求成功
LoginBean loginBean=await event ;
logger.i(loginBean.toJson().toString());
},onError: (e){
logger.i(e);
});
//两个流
var stream2 = Stream.value(apiService.getLogin("TTMALL_APP", "123456", "13041203376", "jia321.."));
Rx.combineLatest2(stream2, stream2, (a, b) => {
});
Terminal运行 flutter packages pub run build_runner build 编译生成 #.g.dart文件
遇到错误Conflicting outputs were detected and the build is unable to prompt for permission to remove them. These outputs must be removed manually or the build can be run with `--delete-conflicting
运行:flutter packages pub run build_runner clean
flutter packages pub run build_runner build --delete-conflicting-outputs
遇到错误 #.g.dart文件 Generator cannot target libraries that have not been migrated to null-safety
更改pubspecy.yaml文件
sdk: ">=2.7.0 <3.0.0" 改为 sdk: ">=2.12.0 <3.0.0" 运行 flutter packages pub run build_runner build 生成 #.g.dart文件 后还原成 sdk: ">=2.7.0 <3.0.0"
android9.0以上设备 网络请求使用https 请求如果是 http 请求 需要在android manifest 加入
<application
...
android:networkSecurityConfig="@xml/network_security_config" //这一行
>
...
</application>
network_security_config.xml 文件
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true" />
</network-security-config>