- 主要涉及到三大块
router , state , api
1.1 路由使用了dio: ^3.0.10
目录结构如下
- application.dart
作用 : 用于静态化import 'package:fluro/fluro.dart'; class Application { static Router router; }
使用
Application.router
- navigator_util.dart
作用 : 这个里面主要是进行路由跳转方法的公共书写
import 'package:flutter/material.dart';
import 'package:fluro/fluro.dart';
import 'package:app/ui/page/index_page.dart';
import 'package:app/ui/page/login.dart';
import './application.dart';
import './routes.dart';
/**
* 这个里面主要是进行路由跳转方法的公共书写
*/
class NavigatorUtil {
// 返回
static void goBack(BuildContext context) {
/// 其实这边调用的是 Navigator.pop(context);
Application.router.pop(context);
}
// 带参数的返回
static void goBackWithParams(BuildContext context, result) {
Navigator.pop(context, result);
}
// 路由返回指定页面
static void goBackUrl(BuildContext context, String title) {
Navigator.popAndPushNamed(context, title);
}
// 跳转到主页面
static void goIndexPage(BuildContext context) {
Application.router.navigateTo(context, Routes.indexPage, replace: true);
}
/// 跳转到 转场动画 页面 , 这边只展示 inFromLeft ,剩下的自己去尝试下,
/// 框架自带的有 native,nativeModal,inFromLeft,inFromRight,inFromBottom,fadeIn,custom
static Future jump(BuildContext context, String title) {
return Application.router.navigateTo(context, title, transition: TransitionType.inFromRight);
/// 指定了 转场动画
}
/// 框架自带的有 native,nativeModal,inFromLeft,inFromRight,inFromBottom,fadeIn,custom
static Future jumpLeft(BuildContext context, String title) {
return Application.router
.navigateTo(context, title, transition: TransitionType.inFromLeft);
/// 指定了 转场动画
}
static Future jumpRemove(BuildContext context) {
return Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (context) => IndexPage(),
),
(route) => route == null);
}
/// 自定义 转场动画
static Future gotransitionCustomDemoPage(BuildContext context, String title) {
var transition = (BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation, Widget child) {
return new ScaleTransition(
scale: animation,
child: new RotationTransition(
turns: animation,
child: child,
),
);
};
return Application.router.navigateTo(context, title,
transition: TransitionType.custom,
/// 指定是自定义动画
transitionBuilder: transition,
/// 自定义的动画
transitionDuration: const Duration(milliseconds: 600));
/// 时间
}
/// 使用 IOS 的 Cupertino 的转场动画,这个是修改了源码的 转场动画
/// Fluro本身不带,但是 Flutter自带
static Future gotransitionCupertinoDemoPage(
BuildContext context, String title) {
return Application.router
.navigateTo(context, title, transition: TransitionType.cupertino);
}
// 跳转到主页面IndexPage并删除当前路由
static void goToHomeRemovePage(BuildContext context) {
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (context) => IndexPage(),
),
(route) => route == null);
}
// 跳转到登录页并删除当前路由
static void goToLoginRemovePage(BuildContext context) {
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (context) => Login(),
),
(route) => route == null);
}
}
使用
NavigatorUtil.jump(context, '/indexPage')
/********************************/
NavigatorUtil.jumpLeft(context, '/normalPage') //附带路由动画, 界面从左边进来
- router_handler.dart
作用 : handler就是每个路由的规则,编写handler就是配置路由规则,比如我们要传递参数,参数的值是什么,这些都需要在Handler中完成。
```bash
import 'package:flutter/material.dart';
import 'package:fluro/fluro.dart';
import 'package:app/ui/page/index_page.dart';
import 'package:app/ui/page/login.dart';
import 'package:app/ui/page/normal_page.dart';
import 'package:app/ui/page/routing_reference.dart';
/**
* handler就是每个路由的规则,编写handler就是配置路由规则,比如我们要传递参数,参数的值是什么,这些都需要在Handler中完成。
*/
// 首页
Handler indexPageHanderl = Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
return IndexPage();
},
);
// 正常路由跳转
Handler normalPageHanderl = Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
return NormalPage();
}
);
// 路由传参
Handler routingReferenceHanderl = Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
String id = params['id'].first;
return RoutingReference(id: id);
}
);
// 登陆页面
Handler loginHanderl = Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
return Login();
}
);
4. routes.dart
作用 : 路由的总配置
涉及到管理路由的名称, 以及管理路由跳转到那个handler规则中
```bash
import 'package:flutter/material.dart';
import 'package:fluro/fluro.dart';
import 'package:app/routers/router_handler.dart';
class Routes {
static String root = '/';
static String indexPage = '/indexPage';
static String normalPage = '/normalPage';
static String routingReference = '/routingReference';
static String login = '/login';
static void configureRoutes(Router router) {
router.notFoundHandler = new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
print('ERROR====>ROUTE WAS NOT FONUND!!!'); // 找不到路由,跳转404页面
print('找不到路由,404');
},
);
// 路由页面配置
router.define(indexPage, handler: indexPageHanderl);
router.define(normalPage, handler: normalPageHanderl);
router.define(routingReference, handler: routingReferenceHanderl);
router.define(login, handler: loginHanderl);
}
}
- 以上整个路由目录结构搭建完毕, 接下来注入main.dart中
// 路由架构
// 参照链接 https://segmentfault.com/a/1190000021488577
// 参照动画 https://blog.csdn.net/z591102/article/details/107839695
import 'package:fluro/fluro.dart';
import 'package:app/routers/application.dart';
import 'package:app/routers/routes.dart';
import "package:app/routers/navigator_util.dart";
void main() {
// 禁用提示
Provider.debugCheckInvalidValueType = null;
// widget和flutter初始化
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
/*****************************/
// 路由部分代码
final router = Router();
Routes.configureRoutes(router);
Application.router = router;
/*****************************/
return MultiProvider(
providers : providers,
child : MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
)
);
}
}
使用路由
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
var style = TextStyle(color: Colors.white);
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(
children: [
Container(
child: Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
color: Colors.redAccent,
height: 48,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
RaisedButton(
onPressed: () => {
NavigatorUtil.jump(context, '/indexPage')
},
child: Text('routerRight'),
),
RaisedButton(
onPressed: () => {
NavigatorUtil.jumpLeft(context, '/normalPage')
},
child: Text('routerLeft'),
),
],
),
),
)
)
),
Container(
color: Colors.deepOrangeAccent,
child: Center(
child: Text('$src', style: style),
)
),
],
),
// This trailing comma makes auto-formatting nicer for build methods.
);
}
}
如何定义一个新的路由
两个步骤
1 . 在router_handler.dart中引入要跳转的组件 , 定制一个新的路由规则
2. 在routes.dart中 新增一个路由地址 , 使用 router.define 注册路由即可
1.2 state使用了provider: ^4.3.2+2
目录结构如下
- provider_manager.dart
作用 : 统一管理state
import 'package:provider/provider.dart';
import 'package:provider/single_child_widget.dart';
import "package:app/view_model/test_model.dart";
List<SingleChildWidget> providers = [
...independentServices,
...dependentServices,
...uiConsumableProviders
];
/// 独立的model
List<SingleChildWidget> independentServices = [
ChangeNotifierProvider<TestModel>(
create: (context) => TestModel(),
),
ChangeNotifierProvider<TestMode2>(
create: (context) => TestMode2(),
),
// ChangeNotifierProvider<LocaleModel>(
// create: (context) => LocaleModel(),
// ),
// ChangeNotifierProvider<GlobalFavouriteStateModel>(
// create: (context) => GlobalFavouriteStateModel(),
// )
];
/// 需要依赖的model
///
/// UserModel依赖globalFavouriteStateModel
List<SingleChildWidget> dependentServices = [
// ChangeNotifierProxyProvider<GlobalFavouriteStateModel, UserModel>(
// create: null,
// update: (context, globalFavouriteStateModel, userModel) =>
// userModel ??
// UserModel(globalFavouriteStateModel: globalFavouriteStateModel),
// )
];
List<SingleChildWidget> uiConsumableProviders = [
// StreamProvider<User>(
// builder: (context) => Provider.of<AuthenticationService>(context, listen: false).user,
// )
];
- provider_widget.dart 和 provider_widget_selector.dart 是一样的, 都是基于provider进一步封装 , 封装的意义在于, 可以更加方便的颗粒化的去build
provider_widget.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
/// Provider封装类
///
/// 方便数据初始化
/// 另外发现进一步封装,都是使用了Consumer来进行包裹, 那么这总控制会更加颗粒化的去build
class ProviderWidget<T extends ChangeNotifier> extends StatefulWidget {
final ValueWidgetBuilder<T> builder;
final T model;
final Widget child;
final Function(T model) onModelReady;
final bool autoDispose;
ProviderWidget({
Key key,
@required this.builder,
@required this.model,
this.child,
this.onModelReady,
this.autoDispose: true,
}) : super(key: key);
_ProviderWidgetState<T> createState() => _ProviderWidgetState<T>();
}
class _ProviderWidgetState<T extends ChangeNotifier>
extends State<ProviderWidget<T>> {
T model;
@override
void initState() {
model = widget.model;
widget.onModelReady?.call(model);
super.initState();
}
@override
void dispose() {
if (widget.autoDispose) model.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<T>.value(
value: model,
child: Consumer<T>(
builder: widget.builder,
child: widget.child,
),
);
}
}
class ProviderWidget2<A extends ChangeNotifier, B extends ChangeNotifier>
extends StatefulWidget {
final Widget Function(BuildContext context, A model1, B model2, Widget child)
builder;
final A model1;
final B model2;
final Widget child;
final Function(A model1, B model2) onModelReady;
final bool autoDispose;
ProviderWidget2({
Key key,
@required this.builder,
@required this.model1,
@required this.model2,
this.child,
this.onModelReady,
this.autoDispose,
}) : super(key: key);
_ProviderWidgetState2<A, B> createState() => _ProviderWidgetState2<A, B>();
}
class _ProviderWidgetState2<A extends ChangeNotifier, B extends ChangeNotifier>
extends State<ProviderWidget2<A, B>> {
A model1;
B model2;
@override
void initState() {
model1 = widget.model1;
model2 = widget.model2;
widget.onModelReady?.call(model1, model2);
super.initState();
}
@override
void dispose() {
if (widget.autoDispose) {
model1.dispose();
model2.dispose();
}
super.dispose();
}
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider<A>.value(value: model1),
ChangeNotifierProvider<B>.value(value: model2),
],
child: Consumer2<A, B>(
builder: widget.builder,
child: widget.child,
));
}
}
provider_widget_selector.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
/// Provider封装类
///
/// 方便数据初始化
class ProviderWidget<T extends ChangeNotifier > extends StatefulWidget {
final ValueWidgetBuilder builder;
final Function(BuildContext, T) selector;
final T model;
final Widget child;
final Function(T model) onModelReady;
final bool autoDispose;
ProviderWidget({
Key key,
@required this.builder,
@required this.model,
this.selector,
this.child,
this.onModelReady,
this.autoDispose,
}) : super(key: key);
_ProviderWidgetState<T> createState() => _ProviderWidgetState<T>();
}
class _ProviderWidgetState<T extends ChangeNotifier>
extends State<ProviderWidget<T>> {
T model;
@override
void initState() {
model = widget.model;
widget.onModelReady?.call(model);
super.initState();
}
@override
void dispose() {
if (widget.autoDispose) model.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<T>.value(
value: model,
child: Selector<T, Symbol>(
selector: widget.selector,
builder: widget.builder,
child: widget.child,
),
);
}
}
- test_model.dart 定义一个state
作用 : 数据的管理源都来自这里 , 继承ChangeNotifier 是因为要有可以执行的notifyListeners方法 , 该方法执行才会进行ui build重新刷新
import 'package:flutter/cupertino.dart';
class TestModel extends ChangeNotifier {
String title = "";
String get value => title;
TestModel({this.title = "2"});
setTitle(value){
title = title + value;
notifyListeners();
}
removeTitle(){
title = "";
notifyListeners();
}
}
class TestMode2 extends ChangeNotifier {
String title = "";
String get value => title;
TestMode2({this.title = "2"});
setTitle(value){
title = title + value;
notifyListeners();
}
removeTitle(){
title = "";
notifyListeners();
}
}
- 在main.dart中引入并注入到顶部
// State架构
// 参考连接 : https://juejin.im/post/6872153613776060424#heading-4
// 注意: 通过Provider来获取被管理的数据的三种方式:Provider.of,Consumer和Selector,它们的功能完全一致,区别仅仅在于刷新的控制粒度。
import 'package:provider/provider.dart';
import 'package:app/config/provider_manager.dart'
void main() {
// 禁用提示
Provider.debugCheckInvalidValueType = null;
// widget和flutter初始化
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
final router = Router();
Routes.configureRoutes(router);
Application.router = router;
/**
* 顶层使用MultiProvider, 注入providers 即可
*/
return MultiProvider(
providers : providers,
child : MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
)
);
}
}
使用
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
var style = TextStyle(color: Colors.white);
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(
children: [
ProviderWidget<TestModel>(
model: TestModel(title : "3"),
builder: (context, TestModel, child){
print("TestMode1重新build");
return Container(
child: Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
color: Colors.redAccent,
height: 48,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text('Child1', style: style),
Text('Model data: ${ TestModel.title}', style: style),
RaisedButton(
onPressed: () => TestModel.setTitle("2"),
child: Text('add'),
),
RaisedButton(
onPressed: () => TestModel.removeTitle(),
child: Text('remove'),
),
],
),
),
)
)
);
}
),
ProviderWidget<TestMode2>(
model: TestMode2(title : "4"),
builder: (context, TestModel, child){
print("TestMode2重新build");
return Container(
child: Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
color: Colors.blueAccent,
height: 48,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text('Child2', style: style),
Text('Model data: ${ TestModel.title}', style: style),
RaisedButton(
onPressed: () => TestModel.setTitle("2"),
child: Text('add'),
),
RaisedButton(
onPressed: () => TestModel.removeTitle(),
child: Text('remove'),
),
],
),
),
)
)
);
}
),
],
),
// This trailing comma makes auto-formatting nicer for build methods.
);
}
}
- 如果要新增一个state ,两个步骤
- view_model目录下创建一个新的state
- provider_manager.dart 引入并注入即可
1.3 api使用了dio: ^3.0.10
目录结构
- NWMethod.dart
作用 : 对请求进行了枚举
enum NWMethod {
GET,
POST,
DELETE,
PUT
}
//使用:NWMethodValues[NWMethod.POST]
const NWMethodValues = {
NWMethod.GET: "get",
NWMethod.POST: "post",
NWMethod.DELETE: "delete",
NWMethod.PUT: "put"
};
- ErrorEntity.dart
作用 : 对报错的返回进行了封装,可根据实际业务场景自行修改
class ErrorEntity {
String code;
String message;
ErrorEntity({this.code, this.message});
}
- EntityFactory.dart
作用 : 对返回的数据进行统一序列化的位置
// json转换辅助工厂,把json转为T
import "package:app/model/user_login.dart";
class EntityFactory {
static T generateOBJ<T>(json) {
if (json == null) {
return null;
}
else if (T.toString() == "UserLogin") {
final res = UserLogin.fromJson(json) as T ;
return res ;
}
else {
return json as T;
}
}
}
- DioManager.dart
作用 : 对请求做了统一的封装
import 'package:dio/dio.dart';
import "package:app/api/BaseEntity.dart";
import "package:app/api/BaseListEntity.dart";
import "package:app/api/baseApi.dart";
import "package:app/api/NWMethod.dart";
import "package:app/api/ErrorEntity.dart";
/**
* dio封装参考这一篇 https://juejin.im/post/6844903708757590024#heading-4
*/
class DioManager {
static final DioManager _shared = DioManager._internal();
factory DioManager() => _shared;
Dio dio;
DioManager._internal() {
if (dio == null) {
BaseOptions options = BaseOptions(
baseUrl: NWApi.baseApi,
contentType: Headers.jsonContentType,
responseType: ResponseType.json,
receiveDataWhenStatusError: false,
connectTimeout: 30000,
receiveTimeout: 3000,
);
dio = Dio(options);
}
}
// 请求,返回参数为 T
// method:请求方法,NWMethod.POST等
// path:请求地址
// params:请求参数
// success:请求成功回调
// error:请求失败回调
Future request<T>(NWMethod method, String path, {Map params, Function(T) success, Function(ErrorEntity) error}) async {
try {
Response response = await dio.request(path, data: params, options: Options(method: NWMethodValues[method]));
if (response != null) {
BaseEntity entity = BaseEntity<T>.fromJson(response.data);
if (entity.code == "000000") {
success(entity.data);
return entity.data;
} else {
error(ErrorEntity(code: entity.code, message: entity.message));
}
} else {
error(ErrorEntity(code: "-1", message: "未知错误"));
}
} on DioError catch(e) {
error(createErrorEntity(e));
}
}
// 请求,返回参数为 List
// method:请求方法,NWMethod.POST等
// path:请求地址
// params:请求参数
// success:请求成功回调
// error:请求失败回调
Future requestList<T>(NWMethod method, String path, {Map params, Function(List<T>) success, Function(ErrorEntity) error}) async {
try {
Response response = await dio.request(path, data: params, options: Options(method: NWMethodValues[method]));
if (response != null) {
BaseListEntity entity = BaseListEntity<T>.fromJson(response.data);
if (entity.code == 0) {
success(entity.data);
} else {
error(ErrorEntity(code: entity.code, message: entity.message));
}
} else {
error(ErrorEntity(code: "-1", message: "未知错误"));
}
} on DioError catch(e) {
error(createErrorEntity(e));
}
}
// 错误信息
ErrorEntity createErrorEntity(DioError error) {
switch (error.type) {
case DioErrorType.CANCEL:{
return ErrorEntity(code:" -1", message: "请求取消");
}
break;
case DioErrorType.CONNECT_TIMEOUT:{
return ErrorEntity(code: "-1", message: "连接超时");
}
break;
case DioErrorType.SEND_TIMEOUT:{
return ErrorEntity(code: "-1", message: "请求超时");
}
break;
case DioErrorType.RECEIVE_TIMEOUT:{
return ErrorEntity(code: "-1", message: "响应超时");
}
break;
case DioErrorType.RESPONSE:{
try {
int errCode = error.response.statusCode;
String errMsg = error.response.statusMessage;
return ErrorEntity(code: "$errCode", message: errMsg);
// switch (errCode) {
// case 400: {
// return ErrorEntity(code: errCode, message: "请求语法错误");
// }
// break;
// case 403: {
// return ErrorEntity(code: errCode, message: "服务器拒绝执行");
// }
// break;
// case 404: {
// return ErrorEntity(code: errCode, message: "无法连接服务器");
// }
// break;
// case 405: {
// return ErrorEntity(code: errCode, message: "请求方法被禁止");
// }
// break;
// case 500: {
// return ErrorEntity(code: errCode, message: "服务器内部错误");
// }
// break;
// case 502: {
// return ErrorEntity(code: errCode, message: "无效的请求");
// }
// break;
// case 503: {
// return ErrorEntity(code: errCode, message: "服务器挂了");
// }
// break;
// case 505: {
// return ErrorEntity(code: errCode, message: "不支持HTTP协议请求");
// }
// break;
// default: {
// return ErrorEntity(code: errCode, message: "未知错误");
// }
// }
} on Exception catch(_) {
return ErrorEntity(code: "-1", message: "未知错误");
}
}
break;
default: {
return ErrorEntity(code:" -1", message: error.message);
}
}
}
}
- BaseListEntity.dart
作用 : 当返回的是这种格式时 {“code”: 0, “message”: “”, “data”: []},进行序列化操作 , 依赖于EntityFactory.dart
import "package:app/api/EntityFactory.dart";
// 当返回的是这种格式时 {“code”: 0, “message”: “”, “data”: []}
class BaseListEntity<T> {
String code;
String message;
List<T> data;
BaseListEntity({this.code, this.message, this.data});
factory BaseListEntity.fromJson(json) {
List<T> mData = List();
if (json['data'] != null) {
//遍历data并转换为我们传进来的类型
(json['data'] as List).forEach((v) {
mData.add(EntityFactory.generateOBJ<T>(v));
});
}
return BaseListEntity(
code: json["code"],
message: json["msg"],
data: mData,
);
}
}
- BaseEntity.dart
作用 : 当返回的数据是这种格式的时候 {“code”: 0, “message”: “”, “data”: {}},进行序列化操作 , 依赖于EntityFactory.dart
import "package:app/api/EntityFactory.dart";
// 当返回的数据是这种格式的时候 {“code”: 0, “message”: “”, “data”: {}}
class BaseEntity<T> {
String code;
String message;
T data;
BaseEntity({this.code, this.message, this.data});
factory BaseEntity.fromJson(json) {
return BaseEntity(
code: json["code"],
message: json["msg"],
// data值需要经过工厂转换为我们传进来的类型
data: EntityFactory.generateOBJ<T>(json) ,
);
}
}
- baseApi.dart
作用 : 对api地址进行统一的管理
class NWApi {
static final baseApi = "https://***.***/";
static final loginPath = "/user/login";
}
- Api.dart
作用 : 所有的api请求调用的方法都在这里面
import "package:app/api/baseApi.dart";
import "package:app/api/DioManager.dart";
import "package:app/api/NWMethod.dart";
import "package:app/model/user_login.dart";
class Api {
///示例请求
static UserLoginApi(Map<String , dynamic> param ) async {
return await DioManager().request<UserLogin>(
NWMethod.POST,
NWApi.loginPath,
params: param,
success: (data) {
},
error: (error) {
print("error code = ${error.code}, massage = ${error.message}");
}
);
}
}
- 使用
// Api架构
// 参照链接 https://juejin.im/post/6844903708757590024#heading-4
import "package:app/api/Api.dart";
void _testRequest() async {
final res = await Api.UserLoginApi({
"user_name": "1111",
"user_pwd": "1111"
});
this.setState(() {
src = "姓名" + res.data.userName + "\n"
+ "密码" + res.data.userPwd + "\n"
+ "userNickName" + res.data.userNickName + "\n"
+ "userQq" + res.data.userQq + "\n"
+ "userEmail" + res.data.userEmail + "\n"
+ "userPhone" + res.data.userPhone + "\n"
+ "token = " + res.data.token + "\n";
});
}
如果要新建一个api,两个步骤
- 在baseApi.dart中新增一个地址
- 在Api.dart创建一个方法
github : https://github.com/2547881370/flutter_structure