/
disposable.dart
105 lines (92 loc) · 2.8 KB
/
disposable.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// Copyright 2024 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import 'dart:async';
import 'package:flutter/foundation.dart';
import '../extensions.dart';
import '../logger.dart';
typedef OnDisposeFunc = Future<void> Function();
mixin _Disposer {
//
final _disposeFuncs = <OnDisposeFunc>[];
bool _isDisposed = false;
bool get isDisposed => _isDisposed;
int get disposeFuncCount => _disposeFuncs.length;
// last added func will be called first when disposing
void onDispose(OnDisposeFunc func) => _disposeFuncs.add(func);
Future<bool> _dispose() async {
if (!_isDisposed) {
logger.finer('[${objectId}] dispose()');
_isDisposed = true;
if (_disposeFuncs.isNotEmpty) {
logger.finer(
'[$objectId] running ${_disposeFuncs.length} dispose funcs...');
// call dispose funcs in reverse order
for (final disposeFunc in _disposeFuncs.reversed) {
await disposeFunc();
}
_disposeFuncs.clear();
logger.finer('[$objectId] dispose complete.');
}
return true;
} else {
logger.warning('[$objectId] unnecessary dispose() called.');
return false;
}
}
}
abstract class Disposable with _Disposer {
@mustCallSuper
Future<bool> dispose() async {
return await _dispose();
}
}
abstract class DisposableChangeNotifier extends ChangeNotifier with _Disposer {
@override
Future<bool> dispose() async {
if (!isDisposed) super.dispose();
return await super._dispose();
}
@override
bool get hasListeners {
if (isDisposed) {
logger.warning('called hasListeners on a disposed ChangeNotifier');
return false;
}
return super.hasListeners;
}
@override
void addListener(VoidCallback listener) {
if (isDisposed) {
logger.warning('called addListener() on a disposed ChangeNotifier');
return;
}
super.addListener(listener);
}
@override
void notifyListeners() {
if (isDisposed) {
logger.warning('called notifyListeners() on a disposed ChangeNotifier');
return;
}
super.notifyListeners();
}
@override
void removeListener(VoidCallback listener) {
if (isDisposed) {
logger.warning('called removeListener() on a disposed ChangeNotifier');
return;
}
super.removeListener(listener);
}
}