Skip to content

Commit 2696bb8

Browse files
committed
fix(android): stop leaking executor thread in getBitmapDrawable
ReactSlider.getBitmapDrawable creates a single-thread ExecutorService per call and never shuts it down, so every setThumbImage call leaks the worker thread for the lifetime of the process. Wrap the submit/get in a try/finally and shut down the executor once the bitmap decode is complete. Behaviour is unchanged; only the now-idle worker thread is reclaimed.
1 parent a7c1169 commit 2696bb8

1 file changed

Lines changed: 29 additions & 24 deletions

File tree

package/android/src/main/java/com/reactnativecommunity/slider/ReactSlider.java

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -280,33 +280,38 @@ private double getStepValue() {
280280
private BitmapDrawable getBitmapDrawable(final String uri) {
281281
BitmapDrawable bitmapDrawable = null;
282282
ExecutorService executorService = Executors.newSingleThreadExecutor();
283-
Future<BitmapDrawable> future = executorService.submit(new Callable<BitmapDrawable>() {
284-
@Override
285-
public BitmapDrawable call() {
286-
BitmapDrawable bitmapDrawable = null;
287-
try {
288-
Bitmap bitmap = null;
289-
if (uri.startsWith("http://") || uri.startsWith("https://") ||
290-
uri.startsWith("file://") || uri.startsWith("asset://") || uri.startsWith("data:")) {
291-
bitmap = BitmapFactory.decodeStream(new URL(uri).openStream());
292-
} else {
293-
int drawableId = getResources()
294-
.getIdentifier(uri, "drawable", getContext()
295-
.getPackageName());
296-
bitmap = BitmapFactory.decodeResource(getResources(), drawableId);
283+
try {
284+
Future<BitmapDrawable> future = executorService.submit(new Callable<BitmapDrawable>() {
285+
@Override
286+
public BitmapDrawable call() {
287+
BitmapDrawable bitmapDrawable = null;
288+
try {
289+
Bitmap bitmap = null;
290+
if (uri.startsWith("http://") || uri.startsWith("https://") ||
291+
uri.startsWith("file://") || uri.startsWith("asset://") || uri.startsWith("data:")) {
292+
bitmap = BitmapFactory.decodeStream(new URL(uri).openStream());
293+
} else {
294+
int drawableId = getResources()
295+
.getIdentifier(uri, "drawable", getContext()
296+
.getPackageName());
297+
bitmap = BitmapFactory.decodeResource(getResources(), drawableId);
298+
}
299+
300+
bitmapDrawable = new BitmapDrawable(getResources(), bitmap);
301+
} catch (Exception e) {
302+
e.printStackTrace();
297303
}
298-
299-
bitmapDrawable = new BitmapDrawable(getResources(), bitmap);
300-
} catch (Exception e) {
301-
e.printStackTrace();
304+
return bitmapDrawable;
302305
}
303-
return bitmapDrawable;
306+
});
307+
try {
308+
bitmapDrawable = future.get();
309+
} catch (Exception e) {
310+
e.printStackTrace();
304311
}
305-
});
306-
try {
307-
bitmapDrawable = future.get();
308-
} catch (Exception e) {
309-
e.printStackTrace();
312+
} finally {
313+
// Without this, every call leaks the worker thread for the lifetime of the process.
314+
executorService.shutdown();
310315
}
311316
return bitmapDrawable;
312317
}

0 commit comments

Comments
 (0)