Yes, using Timer() in Android can cause performance issues, and it is not ideal for UI updates. Here’s why and how to properly handle it.
Why Using Timer() Can Be a Problem in Android?
What is the Best Alternative?
Best Solutions for Your Use Case (Updating a ProgressBar)
1️⃣ Using Handler.postDelayed() (Recommended)
Java:
Handler handler = new Handler();
int progress = 0;
Runnable runnable = new Runnable() {
@Override
public void run() {
if (progress <= 100) {
progressBar.setProgress(progress);
progress += 5;
handler.postDelayed(this, 500);
}
}
};
handler.post(runnable);
Kotlin:
val handler = Handler(Looper.getMainLooper())
var progress = 0
val runnable = object : Runnable {
override fun run() {
if (progress <= 100) {
progressBar.progress = progress
progress += 5
handler.postDelayed(this, 500)
}
}
}
handler.post(runnable)
2️⃣ Using CountDownTimer (Best for a Timed Progress Bar)
Java
new CountDownTimer(10000, 500) { // Total 10 sec, tick every 500ms
public void onTick(long millisUntilFinished) {
int progress = (int) ((10000 - millisUntilFinished) / 100);
progressBar.setProgress(progress);
}
public void onFinish() {
progressBar.setProgress(100);
}
}.start();
Kotlin
object : CountDownTimer(10000, 500) {
override fun onTick(millisUntilFinished: Long) {
val progress = ((10000 - millisUntilFinished) / 100).toInt()
progressBar.progress = progress
}
override fun onFinish() {
progressBar.progress = 100
}
}.start()
3️⃣ Using ScheduledExecutorService (Better than Timer)
Java:
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
runOnUiThread(() -> {
if (progress <= 100) {
progressBar.setProgress(progress);
progress += 5;
}
});
}
}, 0, 500, TimeUnit.MILLISECONDS);
Kotlin:
val scheduler = Executors.newScheduledThreadPool(1)
var progress = 0
scheduler.scheduleAtFixedRate({
runOnUiThread {
if (progress <= 100) {
progressBar.progress = progress
progress += 5
}
}
}, 0, 500, TimeUnit.MILLISECONDS)
4️⃣ Using Coroutine & delay() (Recommended for Modern Kotlin)
import kotlinx.coroutines.*
var progress = 0
fun startProgressBar() {
GlobalScope.launch(Dispatchers.Main) {
while (progress <= 100) {
progressBar.progress = progress
progress += 5
delay(500L)
}
}
}
Conclusion
❌ Timer() is not ideal because it runs on a background thread, making UI updates problematic.
✅ Instead, use: