一、前言
如果对回调函数概念了解的话可以跳过本段内容和第二段内容
在实际开发工作中,有些时候会需要用到回调函数。对应实际生活中的例子,就好像你在网上定了个外卖,然后外卖会在某个时刻送到你手里。在这期间你可以做其他的事情,也不需要关注外卖是怎么做的,怎么送到你手里。
所以回调函数常常用在对某个事件执行时间不确定,需要在这个事件出结果后能主动通知自己的程序逻辑。在程序中的例子就好像是,去执行了一段逻辑,但是不知道这个逻辑什么时候返回结果,需要在逻辑执行完后告诉自己结果再进行下一步操作。
在Flutter中的话可以举这样一个例子,假如有个功能是一个类似于音乐播放器的功能(这个音乐播放器一般来说都是一个单独的模块,使用系统的或者第三方的,反正很少自己去写)。我们需要在音乐播放完毕的时候告诉我们音乐放完了。因为我们不知道音乐什么时候会播放完,所以这时候就需要使用回调函数了。
下面根据这个功能做一个简单的演示程序(这个演示程序没有页面,可以在https://dartpad.cn/ 中进行测试)。后续的几种接口回调的方式都是不同的接口回调的改写
二、示例代码
这个示例代码是一个音乐播放器的代码,三秒后音乐播放停止触发接口回调。
main(){
MediaPlayer mediaPlayer = MediaPlayer();
mediaPlayer.setCompleteCallbackListener((){
print("播放结束了");
});
mediaPlayer.start();
}
//播放器
class MediaPlayer{
Function completeCallback;
start(){
print("开始播放音乐");
//以下为延迟3秒后停止音乐播放器
Future.delayed(Duration(seconds: 3))
.then((value) =>
completeCallback()
);
}
setCompleteCallbackListener(Function completeCallback){
this.completeCallback = completeCallback;
}
}
二、函数
一般来说回调函数都是使用函数来写的,在Dart中,函数是的类型使用Function
进行表示。简单示例如下(关于函数的详细解释不是本篇重点):
//省略返回值
test1(){
print('111111');
}
//携带返回值
void test2(){
print('22222222');
}
三、定义一个函数变量:
在Dart中可以将函数定义为一个变量,代码如下:
import 'package:flutter_test/flutter_test.dart';
main(){
test('测试函数', (){
function1();
});
}
final Function function1 = (){
print('YM---->函数调用');
};
四、函数回调的写法1-Function:
在Dart里面可以把函数作为形参使用,因此回调函数可以使用以下写法:
import 'package:flutter_test/flutter_test.dart';
main(){
test('测试函数', (){
testF((){
print('YM---->回调函数触发');
});
});
}
void testF(Function callBack){
callBack();
}
根据上述知识可以将函数变量赋值与调用的地方分开,来满足实际开发中业务的需要,代码如下:
import 'package:flutter_test/flutter_test.dart';
main(){
test('测试函数', (){
testF((){
print('触发回调函数');
});
testF1();
});
}
Function function1;
void testF(Function callBack){
function1 = callBack;
}
void testF1(){
function1();
}
在实际业务中有时候会在函数中传递一些参数,所以代码可以改写为以下方式:
import 'package:flutter_test/flutter_test.dart';
main(){
test('测试函数', (){
testF((int result){//添加参数,类型为int
print('触发回调函数:$result');
});
testF1();
});
}
Function function1;
void testF(Function callBack){
function1 = callBack;
}
void testF1(){
function1(10);
}
五、函数回调的写法2-typedof:
通过上述方式可以发现,函数回调无法限定参数和返回值,这样在编码中容易出现很多潜在的错误,因此可以使用typedof
进行限制,代码如下:
ps:typedef
的含义是给某一种特定的函数类型起了一个名字,可以认为是一个类型的别名。这样在使用过程中就会进行类型检查
import 'package:flutter_test/flutter_test.dart';
main(){
test('测试函数', (){
testF((int result){//添加参数,类型为int
print('触发回调函数:$result');
});
});
}
// typedef FunctionTest = Function();//定义成这样也是可以的
typedef Function2<int> = void Function(int result);//限定参数和返回值
void testF(Function2<int> function2){
function2(12);
}
六、函数回调的写法3-系统默认:
以上的代码属于Dart中的写法,可以说各个平台都可以使用,不过在日常开发中Flutter也提供了一些默认的回调函数,使我们日常开发更加简洁,这里简单举几个例子,代码如下:
VoidCallback无参回调
这里要注意导入相应包import 'package:flutter/cupertino.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_test/flutter_test.dart';
main(){
test('测试函数', (){
testF((){
print('触发回调函数');
});
testF2();
});
}
VoidCallback _voidCallback;
void testF(VoidCallback callback){
_voidCallback = callback;
}
void testF2(){
_voidCallback();
}
ValueChanged有参回调
这里要注意导入相关的包import 'package:flutter/cupertino.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_test/flutter_test.dart';
main(){
test('测试函数', (){
testF((int result){
print('触发回调函数:$result');
});
testF2();
});
}
ValueChanged<int> _valueCallback;
void testF(ValueChanged<int> callback){
_valueCallback = callback;
}
void testF2(){
_valueCallback(10);
}
关于系统更多的回调函数,可以查看系统源码.
ps: 以上定义的参数类型可以省略,只写参数名,不过为了规范以及减少错误,最好写上