6
6
7
7
import android .os .Handler ;
8
8
import android .os .Looper ;
9
+ import android .util .Log ;
9
10
import androidx .annotation .Nullable ;
10
11
import java .lang .ref .ReferenceQueue ;
11
12
import java .lang .ref .WeakReference ;
@@ -35,6 +36,8 @@ public class InstanceManager {
35
36
// 0 <= n < 2^16.
36
37
private static final long MIN_HOST_CREATED_IDENTIFIER = 65536 ;
37
38
private static final long CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL = 30000 ;
39
+ private static final String TAG = "InstanceManager" ;
40
+ private static final String CLOSED_WARNING = "Method was called while the manager was closed." ;
38
41
39
42
/** Interface for listening when a weak reference of an instance is removed from the manager. */
40
43
public interface FinalizationListener {
@@ -79,11 +82,15 @@ private InstanceManager(FinalizationListener finalizationListener) {
79
82
*
80
83
* @param identifier the identifier paired to an instance.
81
84
* @param <T> the expected return type.
82
- * @return the removed instance if the manager contains the given identifier, otherwise null.
85
+ * @return the removed instance if the manager contains the given identifier, otherwise null if
86
+ * the manager doesn't contain the value or the manager is closed.
83
87
*/
84
88
@ Nullable
85
89
public <T > T remove (long identifier ) {
86
- assertManagerIsNotClosed ();
90
+ if (isClosed ()) {
91
+ Log .w (TAG , CLOSED_WARNING );
92
+ return null ;
93
+ }
87
94
return (T ) strongInstances .remove (identifier );
88
95
}
89
96
@@ -95,11 +102,14 @@ public <T> T remove(long identifier) {
95
102
*
96
103
* @param instance an instance that may be stored in the manager.
97
104
* @return the identifier associated with `instance` if the manager contains the value, otherwise
98
- * null.
105
+ * null if the manager doesn't contain the value or the manager is closed .
99
106
*/
100
107
@ Nullable
101
108
public Long getIdentifierForStrongReference (Object instance ) {
102
- assertManagerIsNotClosed ();
109
+ if (isClosed ()) {
110
+ Log .w (TAG , CLOSED_WARNING );
111
+ return null ;
112
+ }
103
113
final Long identifier = identifiers .get (instance );
104
114
if (identifier != null ) {
105
115
strongInstances .put (identifier , instance );
@@ -114,22 +124,30 @@ public Long getIdentifierForStrongReference(Object instance) {
114
124
* The Dart InstanceManager is considered the source of truth and has the capability to overwrite
115
125
* stored pairs in response to hot restarts.
116
126
*
127
+ * <p>If the manager is closed, the addition is ignored.
128
+ *
117
129
* @param instance the instance to be stored.
118
130
* @param identifier the identifier to be paired with instance. This value must be >= 0.
119
131
*/
120
132
public void addDartCreatedInstance (Object instance , long identifier ) {
121
- assertManagerIsNotClosed ();
133
+ if (isClosed ()) {
134
+ Log .w (TAG , CLOSED_WARNING );
135
+ return ;
136
+ }
122
137
addInstance (instance , identifier );
123
138
}
124
139
125
140
/**
126
141
* Adds a new instance that was instantiated from the host platform.
127
142
*
128
143
* @param instance the instance to be stored.
129
- * @return the unique identifier stored with instance.
144
+ * @return the unique identifier stored with instance. If the manager is closed, returns -1.
130
145
*/
131
146
public long addHostCreatedInstance (Object instance ) {
132
- assertManagerIsNotClosed ();
147
+ if (isClosed ()) {
148
+ Log .w (TAG , CLOSED_WARNING );
149
+ return -1 ;
150
+ }
133
151
final long identifier = nextIdentifier ++;
134
152
addInstance (instance , identifier );
135
153
return identifier ;
@@ -141,11 +159,14 @@ public long addHostCreatedInstance(Object instance) {
141
159
* @param identifier the identifier paired to an instance.
142
160
* @param <T> the expected return type.
143
161
* @return the instance associated with `identifier` if the manager contains the value, otherwise
144
- * null.
162
+ * null if the manager doesn't contain the value or the manager is closed .
145
163
*/
146
164
@ Nullable
147
165
public <T > T getInstance (long identifier ) {
148
- assertManagerIsNotClosed ();
166
+ if (isClosed ()) {
167
+ Log .w (TAG , CLOSED_WARNING );
168
+ return null ;
169
+ }
149
170
final WeakReference <T > instance = (WeakReference <T >) weakInstances .get (identifier );
150
171
if (instance != null ) {
151
172
return instance .get ();
@@ -157,22 +178,38 @@ public <T> T getInstance(long identifier) {
157
178
* Returns whether this manager contains the given `instance`.
158
179
*
159
180
* @param instance the instance whose presence in this manager is to be tested.
160
- * @return whether this manager contains the given `instance`.
181
+ * @return whether this manager contains the given `instance`. If the manager is closed, returns
182
+ * `false`.
161
183
*/
162
184
public boolean containsInstance (Object instance ) {
163
- assertManagerIsNotClosed ();
185
+ if (isClosed ()) {
186
+ Log .w (TAG , CLOSED_WARNING );
187
+ return false ;
188
+ }
164
189
return identifiers .containsKey (instance );
165
190
}
166
191
167
192
/**
168
193
* Closes the manager and releases resources.
169
194
*
170
- * <p>Calling a method after calling this one will throw an {@link AssertionError}. This method
171
- * excluded.
195
+ * <p>Methods called after this one will be ignored and log a warning.
172
196
*/
173
197
public void close () {
174
198
handler .removeCallbacks (this ::releaseAllFinalizedInstances );
175
199
isClosed = true ;
200
+ identifiers .clear ();
201
+ weakInstances .clear ();
202
+ strongInstances .clear ();
203
+ weakReferencesToIdentifiers .clear ();
204
+ }
205
+
206
+ /**
207
+ * Whether the manager has released resources and is not longer usable.
208
+ *
209
+ * <p>See {@link #close()}.
210
+ */
211
+ public boolean isClosed () {
212
+ return isClosed ;
176
213
}
177
214
178
215
private void releaseAllFinalizedInstances () {
@@ -199,10 +236,4 @@ private void addInstance(Object instance, long identifier) {
199
236
weakReferencesToIdentifiers .put (weakReference , identifier );
200
237
strongInstances .put (identifier , instance );
201
238
}
202
-
203
- private void assertManagerIsNotClosed () {
204
- if (isClosed ) {
205
- throw new AssertionError ("Manager has already been closed." );
206
- }
207
- }
208
239
}
0 commit comments