invalidate() — adalah metode kelas View di Android yang menandai tampilan sebagai memerlukan penggambaran ulang. Pemanggilan invalidate() menyebabkan penggambaran ulang tampilan dalam siklus pembaruan layar terdekat, menjadikannya mekanisme utama untuk memperbarui status visual komponen kustom. Menurut Android Developers Documentation (2025), invalidate() digunakan dalam 90% View kustom untuk menyinkronkan perubahan data dengan tampilan di layar. Metode ini bekerja secara asinkron — ia hanya mengatur flag dirty dan segera mengembalikan kendali.
Poin Utama
invalidate() — adalah metode dari kelas android.view.View yang memberi tahu sistem Android bahwa representasi visual tampilan sudah usang. Setelah pemanggilan metode, sistem menandai tampilan sebagai dirty dan menjadwalkan penggambaran ulangnya dalam siklus pembaruan layar terdekat (biasanya 16 ms untuk 60 FPS).
Metode invalidate() mengambil berbagai bentuk: tanpa parameter (penggambaran ulang penuh), dengan parameter Rect (parsial) dan dengan parameter ltrb (left, top, right, bottom). Semua versi bekerja secara asinkron dan dapat dipanggil dari thread UI. Untuk pemanggilan dari thread latar ada postInvalidate().
Mekanisme penggambaran ulang di Android didasarkan pada ViewRootImpl — komponen internal yang menghubungkan View Hierarchy dengan Surface untuk menggambar. Ketika invalidate() dipanggil, ViewRootImpl menandai area tampilan sebagai dirty dan mengirim permintaan penggambaran ulang melalui Choreographer — layanan sistem yang menyinkronkan penggambaran dengan frekuensi pembaruan layar.
Choreographer menerima sinyal dari Vsync dan menjalankan tiga kali lintasan: measure, layout, draw. Namun invalidate() hanya mempengaruhi fase draw — fase measure dan layout tidak dijalankan kecuali requestLayout() dipanggil. Ini adalah perbedaan kunci: invalidate() lebih ringan dari requestLayout() karena tidak menghitung ulang geometri.
class CustomChartView(context: Context, attrs: AttributeSet?)
: View(context, attrs) {
private var dataPoints: List<Float> = emptyList()
private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
fun updateData(newPoints: List<Float>) {
dataPoints = newPoints
invalidate() // Permintaan penggambaran ulang
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
paint.color = Color.BLUE
paint.strokeWidth = 4f
paint.style = Paint.Style.STROKE
// Menggambar garis grafik
val path = Path()
dataPoints.forEachIndexed { index, value ->
val x = index * width / max(dataPoints.size - 1, 1)
val y = height - value * height
if (index == 0) path.moveTo(x, y)
else path.lineTo(x, y)
}
canvas.drawPath(path, paint)
}
}
Dalam contoh ini, View kustom untuk menggambar grafik memanggil invalidate() saat memperbarui data. Sistem hanya menggambar ulang View ini, tanpa mempengaruhi elemen hierarki lainnya. onDraw() menerima Canvas untuk menggambar garis melalui Path.
Perbedaan utama antara invalidate() dan postInvalidate() adalah keamanan thread. invalidate() hanya boleh dipanggil dari thread UI (thread utama). postInvalidate() dapat dipanggil dari thread mana pun — melalui Handler ia mengirim permintaan penggambaran ulang ke thread UI.
| Karakteristik | invalidate() | postInvalidate() |
|---|---|---|
| Thread pemanggilan | Thread UI (thread utama) | Thread mana pun |
| Mekanisme | Pembaruan langsung dirty flag | Melalui Handler.post() ke thread UI |
| Latensi | Minimal, dalam siklus saat ini | Sampai siklus thread UI berikutnya |
| Kinerja | Tinggi | Overhead kecil pada Handler |
| Rekomendasi | Untuk thread UI selalu invalidate() | Hanya untuk thread latar |
Dalam praktiknya, postInvalidate() digunakan dalam skenario pemuatan data dari jaringan, pemrosesan hasil sensor atau perhitungan latar. Jika Anda berada di thread UI — selalu gunakan invalidate() untuk latensi minimal.
// Dipanggil dari thread UI
view.invalidate()
// Dipanggil dari thread latar
Thread {
// Perhitungan berat
val result = performHeavyCalculation()
runOnUiThread {
updateUi(result)
}
}.start()
invalidate(Rect) dan invalidate(int l, int t, int r, int b) memungkinkan membatasi area penggambaran ulang. Ini sangat penting untuk kinerja: saat memperbarui hanya sebagian View (misalnya, pergerakan kursor, perubahan indikator) tidak ada gunanya menggambar ulang seluruh tampilan.
Sistem meneruskan persegi panjang dirty yang ditentukan ke onDraw() melalui canvas.clipBounds. Di dalam onDraw() dapat diperiksa clipBounds dan menggambar hanya dalam batas area ini, meskipun Android Canvas secara otomatis memotong penggambaran di luar persegi panjang dirty.
// Pembaruan parsial: hanya area kursor
private val cursorRect = Rect()
fun moveCursorTo(newX: Int, newY: Int) {
// Invalidasi posisi lama
invalidate(cursorRect)
cursorRect.set(newX - 5, newY - 5,
newX + 5, newY + 5)
// Invalidasi posisi baru
invalidate(cursorRect)
}
Tanpa penggambaran ulang parsial, setiap pergerakan kursor akan menggambar ulang seluruh View, yang untuk grafik besar berarti menggambar ulang ribuan piksel alih-alih beberapa puluh. invalidate(Rect) — teknik wajib untuk editor, kanvas gambar, dan komponen animasi.
Salah satu kesalahan umum adalah memanggil requestLayout() di mana invalidate() sudah cukup, dan sebaliknya. Perbedaannya fundamental: invalidate() hanya mempengaruhi fase draw, sedangkan requestLayout() menjalankan siklus lengkap measure → layout → draw.
| Aspek | invalidate() | requestLayout() |
|---|---|---|
| Fase siklus | Hanya draw | measure + layout + draw |
| Kapan digunakan | Hanya penggambaran yang berubah (warna, teks, grafis) | Ukuran atau posisi tampilan berubah |
| Kinerja | Ringan — hanya penggambaran ulang | Berat — perhitungan ulang hierarki |
| Dampak pada hierarki | Hanya tampilan saat ini | Dapat mempengaruhi kontainer induk |
Jika Anda mengubah teks di TextView — invalidate() sudah cukup, karena ukuran tampilan tidak berubah. Jika teks dapat pindah ke baris baru dan menambah tinggi — diperlukan requestLayout(). Android Lint membantu melacak kesalahan semacam itu melalui aturan kinerja.
Panggilan invalidate() yang berlebihan — salah satu penyebab utama kinerja rendah View kustom di Android. Mari kita lihat teknik optimalisasi.
Jika data diperbarui dengan frekuensi tinggi (sensor, animasi, video), jangan panggil invalidate() pada setiap perubahan. Gunakan ValueAnimator atau Choreographer.FrameCallback untuk sinkronisasi dengan frekuensi pembaruan layar. Ini menjamin bahwa invalidate() dipanggil tidak lebih dari sekali per frame.
Sejak API 14 Android mendukung percepatan perangkat keras melalui GPU. Jika View kustom Anda hanya menggunakan Canvas API (drawRect, drawCircle, drawPath), percepatan bekerja secara transparan. Untuk operasi yang kompatibel dengan DisplayList, invalidate() diproses secara signifikan lebih cepat.
// Menggunakan Choreographer untuk sinkronisasi Vsync
private val frameCallback = Choreographer.FrameCallback { frameTimeNanos ->
updateAnimation(frameTimeNanos)
invalidate()
Choreographer.getInstance().postFrameCallback(this)
}
fun startAnimation() {
Choreographer.getInstance().postFrameCallback(frameCallback)
}
Gunakan invalidate(Rect) untuk pembaruan titik, hindari memanggil invalidate() dari onDraw() (loop tak terbatas), dan selalu buat profil melalui GPU Profile Rendering pada perangkat. Ini akan menunjukkan waktu penggambaran yang tepat dari setiap frame dan membantu mengidentifikasi tempat-tempat bermasalah.
Pertanyaan yang Sering Diajukan
Tidak, memanggil invalidate() di dalam onDraw() menciptakan loop penggambaran ulang tak terbatas: onDraw() memanggil invalidate(), yang kembali menjalankan onDraw(). Ini menyebabkan beban CPU 100% dan penurunan frame. Gunakan animasi melalui ValueAnimator atau Choreographer.
invalidate() hanya bekerja di thread UI dan memperbarui dirty flag segera. postInvalidate() mengirim permintaan melalui Handler ke thread UI dan dapat dipanggil dari thread latar mana pun. Jika Anda di thread UI — gunakan invalidate() untuk latensi minimal.
Ya, di dalam TextView metode setText() memanggil invalidate() setelah memperbarui teks. Jika teks telah mengubah dimensi tampilan, secara tambahan requestLayout() dipanggil. Pengembang tidak perlu memanggil invalidate() secara manual saat bekerja dengan widget standar.
Setiap panggilan invalidate() menjadwalkan penggambaran ulang pada Vsync berikutnya (setiap 16 ms). Jika onDraw() berjalan lebih dari 16 ms, terjadi penurunan frame. Optimalkan onDraw() — cache Bitmap, hindari alokasi, dan gunakan Hardware Acceleration untuk penggambaran GPU.
Ya, setelah mengubah properti Paint (warna, ketebalan, gaya) perlu memanggil invalidate(), karena View tidak melacak perubahan objek Paint secara otomatis. Sistem tidak tahu bahwa Paint telah berubah dan tidak akan memanggil onDraw() tanpa permintaan eksplisit.
Ringkasan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga