Класс Finalizable
Интерфейс-маркер для объектов, которые не следует финализировать слишком рано.
Гарантируется, что любая локальная переменная со статическим типом, который включает Finalizable, будет оставаться живой до выхода из блока кода, в котором находится эта переменная.
Тип включает Finalizable, если выполняется одно из условий:
- тип является не-
NeverподтипомFinalizableили - тип является
T?илиFutureOr<T>, гдеTвключаетFinalizable.
Другими словами, пока на объект ссылается такая переменная, гарантируется, что он не будет считаться недостижимым, а сама переменная считается живой в течение всего времени действия своей области видимости, даже после последнего обращения к ней.
Если тип переменной не включает этот интерфейс-маркер, значение переменной может быть собрано сборщиком мусора до полного выполнения окружающей области видимости, если заведомо известно, что к переменной больше не будут обращаться. Это, в свою очередь, может вызвать выполнение обратного вызова NativeFinalizer. Если тип переменной включает Finalizable, обратный вызов NativeFinalizer не будет выполняться до завершения текущего кода, использующего эту переменную.
Например, finalizable остается живым во время выполнения someNativeCall:
void myFunction() {
final finalizable = MyFinalizable(Pointer.fromAddress(0));
someNativeCall(finalizable.nativeResource);
}
void someNativeCall(Pointer nativeResource) {
// ..
}
class MyFinalizable implements Finalizable {
final Pointer nativeResource;
MyFinalizable(this.nativeResource);
} Методы класса, реализующего Finalizable, сохраняют объект this живым на протяжении выполнения метода. Значение this рассматривается как локальная переменная.
Например, this остается живым во время выполнения someNativeCall в myFunction:
class MyFinalizable implements Finalizable {
final Pointer nativeResource;
MyFinalizable(this.nativeResource);
void myFunction() {
someNativeCall(nativeResource);
}
}
void someNativeCall(Pointer nativeResource) {
// ..
} Рекомендуется реализовывать логику, связанную с финализируемыми объектами, в виде методов класса, реализующего Finalizable.
Если внутри блочной области видимости, в которой объявлена переменная, создается замыкание, содержащее ссылку на эту переменную, она остается живой, пока существует объект замыкания или выполняется тело такого замыкания.
Например, finalizable остается живым благодаря объекту замыкания и до конца выполнения тела замыкания:
void doSomething() {
final resourceAction = myFunction();
resourceAction(); // `finalizable` is alive until this call returns.
}
void Function() myFunction() {
final finalizable = MyFinalizable(Pointer.fromAddress(0));
return () {
someNativeCall(finalizable.nativeResource);
};
}
void someNativeCall(Pointer nativeResource) {
// ..
}
class MyFinalizable implements Finalizable {
final Pointer nativeResource;
MyFinalizable(this.nativeResource);
} Замыкания сохраняют живыми только захваченные переменные, а не все переменные.
Например, finalizable не остается живым благодаря возвращенному объекту замыкания:
void Function() myFunction() {
final finalizable = MyFinalizable(Pointer.fromAddress(0));
final nativeResource = finalizable.nativeResource;
return () {
someNativeCall(nativeResource);
};
}
void someNativeCall(Pointer nativeResource) {
// ..
}
class MyFinalizable implements Finalizable {
final Pointer nativeResource;
MyFinalizable(this.nativeResource);
} Вероятно, это ошибка, если ресурс, извлеченный из финализируемого объекта, выходит за пределы области видимости финализируемой переменной, из которой он был получен.
Поведение переменных Finalizable также распространяется на асинхронные функции. Такие переменные остаются живыми, пока внутри области видимости, в которой они объявлены, или в замыкании, захватывающем эту переменную, может выполняться какой-либо код, даже если при выполнении возникают асинхронные задержки.
Например, finalizable остается живым во время await someAsyncCall():
Future<void> myFunction() async {
final finalizable = MyFinalizable();
await someAsyncCall();
}
Future<void> someAsyncCall() async {
// ..
}
class MyFinalizable implements Finalizable {
// ..
} В асинхронном коде извлечение ресурса из финализируемого объекта с выходом за пределы области видимости финализируемой переменной, из которой он был получен, также, вероятно, является ошибкой. Если необходимо извлечь ресурс из Finalizable, следует обеспечить, чтобы область видимости, в которой определен Finalizable, существовала дольше ресурса, ожидая завершения любого асинхронного кода, использующего этот ресурс, с помощью await.
Например, this остается живым, пока resource больше не используется в useAsync1, но не в useAsync2 и useAsync3:
class MyFinalizable {
final Pointer<Int8> resource;
MyFinalizable(this.resource);
Future<int> useAsync1() async {
return await useResource(resource);
}
Future<int> useAsync2() async {
return useResource(resource);
}
Future<int> useAsync3() {
return useResource(resource);
}
}
/// Does not use [resource] after the returned future completes.
Future<int> useResource(Pointer<Int8> resource) async {
return resource.value;
} Асинхронная функция может зависнуть на await, так что система времени выполнения сможет определить, что этот await никак не может завершиться. В этом случае код после await никогда не будет выполнен, включая блоки finally, и переменная может считаться мертвой вместе со всем остальным.
Если вы не собираетесь самостоятельно сохранять переменную живой, передавайте финализируемый объект другим функциям, а не только его ресурс.
Например, finalizable не остается живым благодаря myFunction после завершения выполнения в своей области видимости, хотя someAsyncCall все еще может продолжить выполнение. Однако finalizable остается живым благодаря самому someAsyncCall:
void myFunction() {
final finalizable = MyFinalizable();
someAsyncCall(finalizable);
}
Future<void> someAsyncCall(MyFinalizable finalizable) async {
// ..
}
class MyFinalizable implements Finalizable {
// ..
} - Аннотации
-
- @Since('2.17')
Свойства
- hashCode → int только для чтенияунаследовано
- Хеш-код этого объекта.
- runtimeType → Type только для чтенияунаследовано
- Представление типа объекта во время выполнения.
Методы
- noSuchMethod(
Invocation invocation) → dynamic унаследовано - Вызывается при обращении к несуществующему методу или свойству.
- toString(
) → String унаследовано - Строковое представление этого объекта.
Операторы
- operator ==(
Object other) → bool унаследовано - Оператор равенства.
© 2012 the Dart project authors
Licensed under the BSD 3-Clause "New" or "Revised" License.
https://api.dart.dev/stable/2.19.6/dart-ffi/Finalizable-class.html