From 2696bb818067c8642f846897ff7eef469029fc5f Mon Sep 17 00:00:00 2001 From: pataar Date: Tue, 5 May 2026 21:27:17 +0200 Subject: [PATCH] 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. --- .../slider/ReactSlider.java | 53 ++++++++++--------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/package/android/src/main/java/com/reactnativecommunity/slider/ReactSlider.java b/package/android/src/main/java/com/reactnativecommunity/slider/ReactSlider.java index 19808941..36c9fba2 100644 --- a/package/android/src/main/java/com/reactnativecommunity/slider/ReactSlider.java +++ b/package/android/src/main/java/com/reactnativecommunity/slider/ReactSlider.java @@ -280,33 +280,38 @@ private double getStepValue() { private BitmapDrawable getBitmapDrawable(final String uri) { BitmapDrawable bitmapDrawable = null; ExecutorService executorService = Executors.newSingleThreadExecutor(); - Future future = executorService.submit(new Callable() { - @Override - public BitmapDrawable call() { - BitmapDrawable bitmapDrawable = null; - try { - Bitmap bitmap = null; - if (uri.startsWith("http://") || uri.startsWith("https://") || - uri.startsWith("file://") || uri.startsWith("asset://") || uri.startsWith("data:")) { - bitmap = BitmapFactory.decodeStream(new URL(uri).openStream()); - } else { - int drawableId = getResources() - .getIdentifier(uri, "drawable", getContext() - .getPackageName()); - bitmap = BitmapFactory.decodeResource(getResources(), drawableId); + try { + Future future = executorService.submit(new Callable() { + @Override + public BitmapDrawable call() { + BitmapDrawable bitmapDrawable = null; + try { + Bitmap bitmap = null; + if (uri.startsWith("http://") || uri.startsWith("https://") || + uri.startsWith("file://") || uri.startsWith("asset://") || uri.startsWith("data:")) { + bitmap = BitmapFactory.decodeStream(new URL(uri).openStream()); + } else { + int drawableId = getResources() + .getIdentifier(uri, "drawable", getContext() + .getPackageName()); + bitmap = BitmapFactory.decodeResource(getResources(), drawableId); + } + + bitmapDrawable = new BitmapDrawable(getResources(), bitmap); + } catch (Exception e) { + e.printStackTrace(); } - - bitmapDrawable = new BitmapDrawable(getResources(), bitmap); - } catch (Exception e) { - e.printStackTrace(); + return bitmapDrawable; } - return bitmapDrawable; + }); + try { + bitmapDrawable = future.get(); + } catch (Exception e) { + e.printStackTrace(); } - }); - try { - bitmapDrawable = future.get(); - } catch (Exception e) { - e.printStackTrace(); + } finally { + // Without this, every call leaks the worker thread for the lifetime of the process. + executorService.shutdown(); } return bitmapDrawable; }