flutter dio的简单使用以及简单封装

1、毫无疑问,pubspec.yaml引入

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.8
  dio: ^5.8.0+1
  provider: ^6.1.5

provider还是有必要存在的

2、来个StatelessWidget

main.dart
import 'package:day01/main_provider.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() {
  runApp(
    MultiProvider(
      providers: [ChangeNotifierProvider(create: (context) => MainProvider())],
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  Widget build(BuildContext context) {
    final provider = Provider.of<MainProvider>(context);

    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(provider.text),
            ElevatedButton(
              onPressed: provider.getList,
              child: const Text('请求数据'),
            ),
          ],
        ),
      ),
    );
  }
}

这里还是StatelessWidget,状态我暂时是打算全扔到provider里去管理,所以现在莫慌,接下来整provider。

3、补上刚上来的MainProvider

main_provider.dart
import 'dart:convert';

import 'package:day01/bean/base_bean.dart';
import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';

class MainProvider with ChangeNotifier {

  String _text = '';
  String get text => _text;

  void getHello() async {
    try{
      var response=await Dio().get("http://192.168.5.116:20080/contact/helloworld");
      _text=BaseBean.fromJson(response.data).data.toString();
    }catch(e){
      _text='请求出错了:$e';
    }
    notifyListeners();
  }
}

到这里就可以运行一下,理想效果是:点击一下请求数据按钮,调用provider的getHello方法,然后请求一个demo接口,返回一个hello字符,通过notifyListeners()更新从而显示到页面的Text上。

好了问题来了:我总不能每请求一次就new一个Dio()吧
flutter再简单dio再好用,也禁不住这么个造法啊~做安卓开发的你每次请求都new一个Retrofit或者OkHttp你试试,保证敲你狗头!

4、上菜!Dio封装!

既然都做封装了,单例总得有吧,baseUrl总得有吧,简单的拦截器也总得有吧

dio_util.dart
import 'package:dio/dio.dart';

class DioUtil {
  String _baseUrl = 'http://192.168.5.116:20080';

  static DioUtil _instance = DioUtil._internal();
  Dio? _dio;

  factory DioUtil() => _instance;

  static DioUtil getInstance() => _instance;

  DioUtil._internal() {
    _dio = Dio(BaseOptions(baseUrl: _baseUrl));
    _dio!.interceptors.add(LogInterceptor(responseBody: true));
  }

  get(
    String url,
    Map<String, dynamic>? queryParameters,
    Function() load,
    Function(dynamic data) success,
    Function(String reason) fail,
  ) async {
    load();
    var response = await _dio!.get(url, queryParameters: queryParameters);
    if (response.statusCode == 200) {
      if (response.data['code'] == 200) {
        success(response.data);
      } else {
        fail(response.data['msg']);
      }
    } else {
      fail(response.statusCode!.toString() + "_" + response.statusMessage!);
    }
  }

  post(
      String url,
      Object? data,
      Function() load,
      Function(dynamic data) success,
      Function(String reason) fail) async{
    load();
    var response = await _dio!.post(url, data: data);
    if (response.statusCode == 200) {
      if (response.data['code'] == 200) {
        success(response.data);
      } else {
        fail(response.data['msg']);
      }
    } else {
      fail(response.statusCode!.toString() + "_" + response.statusMessage!);
    }
  }

  addHeader(String key, String value) {
    _dio!.options.headers[key] = value;
  }
}

好的,单例有了,单例范例在此:

class Singleton {
  static final Singleton _singleton = Singleton._internal();

  factory Singleton() => _singleton;

  Singleton._internal() {
    // TODO
  }
}

看样子照着抄就行

_dio!.interceptors.add(LogInterceptor(responseBody: true))

这个是添加自带的日志拦截器的,用于打印请求响应

然后给get和post整了个接-化-发
:触发load()函数,给前端通知,然后开始请求
:请求到东西没,成功了没,以及各种没成功case
:直接拿lambda表达式/函数(不管叫啥都是一个意思)把刚才处理好的结果扔出去

最后再写一个加token的方法:

 addHeader(String key, String value) {
    _dio!.options.headers[key] = value;
  }

写这么简单仅为演示,理论上讲应该是扔Map<String,dynamic>的

5、dio封装好了咋用?

上菜!

main_provider.dart
import 'dart:convert';

import 'package:day01/bean/base_bean.dart';
import 'package:day01/dio_util.dart';
import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';

class MainProvider with ChangeNotifier {
  String _text = '';

  String get text => _text;


  void getHello() async {
    await DioUtil.getInstance().get("http://192.168.5.116:20080/contact/helloworld",null,(){
      _text = "loading";
      notifyListeners();
    },(data){
      BaseBean bean = BaseBean.fromJson(data);
      _text = bean.data.toString();
      notifyListeners();
    },(reason){
      _text = reason;
      notifyListeners();

    });
  }
}

齐活!完事!

上一篇
下一篇