flutter dio+rxdart+retrofit 自动解析请求框架

6,184 阅读2分钟

线上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>