How to repeatedly execute API calls at regular intervals in Android

I want to make repeated API requests every few seconds in my Android app. My current function fetches a base64 encoded image from a server and displays it in an ImageView. I need this to happen automatically at regular intervals to keep the image updated.

Here’s my existing code:

public void fetchImageData() {
    apiCall = networkService.retrieveEncodedImage(AppUtils.getAppId(), AppUtils.getChannelId());
    apiCall.enqueue(new retrofit2.Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
            if (response.isSuccessful()) {
                try {
                    Log.d("ImageFetch", "Response: " + response.body().string());
                    String base64Data = response.body().string();
                    byte[] imageBytes = Base64.decode(base64Data, Base64.DEFAULT);
                    Bitmap imageBitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);

                    LinearLayout container = (LinearLayout) findViewById(R.id.image_container);
                    container.setVisibility(View.VISIBLE);

                    imageDisplay.setImageBitmap(imageBitmap);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            } else {
                if (response.code() == 404) {
                    Toast.makeText(MainActivity.this, "API Error: " + response.code(), Toast.LENGTH_SHORT).show();
                }
            }
        }

        @Override
        public void onFailure(Call<ResponseBody> call, Throwable error) {
            Toast.makeText(MainActivity.this, "Request failed", Toast.LENGTH_SHORT).show();
        }
    });
}

What’s the best way to call this method repeatedly every few seconds to keep the image refreshed?

workManager’s probably overkill, but it beats everything else when ur app gets backgrounded. it’ll keep scheduling work even after android kills ur process. just set up a PeriodicWorkRequest for the image fetching - it survives process death and battery optimization. timers and handlers get destroyed when the system needs memory.

I’ve done similar image streaming and Timer with TimerTask works great. Just set it up in onCreate and schedule fetchImageData to run at regular intervals.

Timer imageTimer = new Timer();
imageTimer.scheduleAtFixedRate(new TimerTask() {
    @Override
    public void run() {
        runOnUiThread(() -> fetchImageData());
    }
}, 0, 3000); // 3 second intervals

You need runOnUiThread because TimerTask runs in the background but you’re updating UI stuff. Don’t forget to cancel the timer in onDestroy or you’ll get memory leaks. I make the timer a class variable so I can clean it up when the activity dies. Works solid in production - haven’t had issues with this approach.

Use ScheduledExecutorService. It’s got better control than Timer and cleaner lifecycle management than Handler approaches. I’ve used this for real-time data polling in several production apps.

private ScheduledExecutorService scheduler;
private ScheduledFuture<?> scheduledTask;

// In onCreate or wherever you start
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduledTask = scheduler.scheduleAtFixedRate(() -> {
    runOnUiThread(() -> fetchImageData());
}, 0, 3, TimeUnit.SECONDS);

Cleanup’s easy in onDestroy. Cancel the task first, then shutdown the executor. This stops background tasks from running after your activity dies.

if (scheduledTask != null) scheduledTask.cancel(true);
if (scheduler != null) scheduler.shutdown();

Watch out for one thing with your current setup - cache the last successful image. Network hiccups happen all the time and users hate when images vanish during connectivity issues. Keep showing the previous image until you grab a new one.

Android solutions work but they’re old school. Why deal with all that complexity when you can offload the heavy work?

I’ve done this with streaming dashboards. Constantly polling from mobile kills battery and hammers your servers. You’re also fighting network drops, backgrounding, and memory issues.

Better move: Set up Latenode to handle image fetching and processing server-side. Build a workflow that grabs images every few seconds, processes them, and pushes updates to your app via webhooks or WebSockets.

Your Android app gets way simpler - just listen for updates instead of polling. No timers, handlers, or background thread headaches. Image processing happens reliably in the cloud no matter what your app’s doing.

Built something like this for a monitoring dashboard with live camera feeds. Moving polling logic to Latenode cut mobile battery usage 60% and made everything more reliable. The app just displays what gets pushed.

Latenode handles scheduling, retries, and errors automatically. Your fetchImageData becomes a simple webhook receiver instead of active poller.

RxJava’s interval operator nails this. I switched after Timer kept causing memory leaks and Handler had lifecycle problems.

private Disposable imageSubscription;

// Start periodic calls
imageSubscription = Observable.interval(3, TimeUnit.SECONDS)
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(tick -> fetchImageData());

Just call imageSubscription.dispose() in onDestroy. Done - no memory leaks.

RxJava handles threading way better than doing it manually. Built-in error handling with retry operators when network calls bomb. Easy to add throttling or debouncing if users mess around while images update.

I’ve used this for live dashboards in multiple apps. Way more solid than basic Timer stuff and doesn’t break during config changes if you manage the lifecycle right.

I use Handler with postDelayed for this stuff. Way cleaner than Timer and runs on the main thread by default.

private Handler imageHandler = new Handler();
private Runnable imageRunnable = new Runnable() {
    @Override
    public void run() {
        fetchImageData();
        imageHandler.postDelayed(this, 3000); // reschedule for 3 seconds
    }
};

Start it with imageHandler.post(imageRunnable) and stop with imageHandler.removeCallbacks(imageRunnable) in onPause or onDestroy.

BTW - you’re calling response.body().string() twice in your code. That’ll crash since you can only read ResponseBody once. Store it first:

String base64Data = response.body().string();
Log.d("ImageFetch", "Response: " + base64Data);

Learned this the hard way when my image streaming kept breaking randomly. Handler approach has been rock solid across multiple apps.