它和java的finalize方法有点像
/// 文件a
import 'dart:ffi';
import 'package:ffi/ffi.dart';
class FfiData {
/// Uint64的字节数
static const _sizeInBytes = 8;
/// 要是final的,因为它和FfiData对象是一对一共生的关系,FfiData对象被GC清理了,其内部的pointer也会被清理(清理逻辑自己写,通过Finalizer实现)
final Pointer<Uint64> pointer;
/// 注意,这个是static final的,因为它充当着GC工具的作用,可以为多个FfiData对象清理内部引用的ffi数据,所以必须是static final的
static final _finalizer = Finalizer<Pointer<Uint64>>((ptr) {
/// 当当前的FfiData被GC释放时,会触发这里,这个是attach方法里绑定了这样的关系
print("释放了吗?");
malloc.free(ptr);
});
void test() {
print("数据指针地址:${pointer.address}");
}
/// 在构造方法里allocate Pointer指向的空间数据
FfiData(): pointer = malloc.allocate(FfiData._sizeInBytes) {
// 注意这段代码,它表示注册当前FfiData对象,和这个FfiData对象释放后要传递给Finalizer初始化时的回调函数的对象
// 这样放this被GC释放时,DVM会拿到其对应的pointer对象,调用_finalizer初始化时的构造方法里的回调函数;
_finalizer.attach(this, pointer);
}
}
/// 文件b
String template = "一段很长的内容";
void main() {
FfiData? data = FfiData();
data.test();
// 如果不设置为null会导致下面的循环虽然触发了GC,但是data被认为仍然有用而不会被释放,从而不触发对应的Finalizer对象的回调函数
data = null;
int size = 10000;
List<String> list = [];
// 用于触发GC
for (int i = 0; i < size; i++) {
list.add(template + i.toString());
}
print("size:${list.length}");
}