Adapter — apa itu, pola transformasi antarmuka untuk pengembangan mobile

Penulis: IT Sectr Diterbitkan: 2026-02-18 Waktu membaca: 10 mnt

Adapter — adalah pola desain struktural yang mengubah antarmuka suatu kelas ke antarmuka lain yang diharapkan oleh klien. Dalam pengembangan mobile, Adapter paling sering digunakan di RecyclerView.Adapter untuk Android dan UITableViewDataSource untuk iOS. Menurut data Google I/O (2024), RecyclerView digunakan di 95% aplikasi Android untuk menampilkan daftar, dan masing-masing memerlukan implementasi Adapter sendiri.

Poin Utama

  • Adapter — pola struktural yang memungkinkan objek dengan antarmuka yang tidak kompatibel bekerja bersama
  • RecyclerView.Adapter — implementasi pola di Android, mengubah data menjadi ViewHolder untuk daftar
  • UITableViewDataSource — implementasi di iOS yang menggabungkan pola Adapter dan DataSource
  • Object Adapter menggunakan komposisi: adapter berisi referensi ke objek yang diadaptasi
  • Class Adapter menggunakan pewarisan berganda — hanya mungkin di C++, tidak tersedia di Java/Swift/Kotlin

Apa itu pola Adapter?

Adapter — pola struktural yang memecahkan masalah ketidakcocokan antarmuka. Ia membungkus satu objek (Adaptee) ke dalam kelas (Adapter) dengan antarmuka yang diharapkan klien (Target). Klien bekerja dengan Target, tanpa mengetahui keberadaan Adaptee. Ini adalah varian dari pola Wrapper.

Kotlin
// Kelas yang ada dengan antarmuka yang tidak kompatibel
class LegacyAuthApi {
    fun loginWithToken(token: String): Map {
        return mapOf("status" to "ok", "user_id" to 42)
    }
}

// Antarmuka target (yang diharapkan klien)
interface AuthService {
    suspend fun login(credentials: Credentials): Result
}

// Adapter — mengubah LegacyAuthApi menjadi AuthService
class LegacyAuthAdapter(
    private val legacyApi: LegacyAuthApi
) : AuthService {
    override suspend fun login(credentials: Credentials): Result {
        val token = "${credentials.login}:${credentials.password}"
            .encodeToByteArray().let { Base64.encodeToString(it) }
        val response = legacyApi.loginWithToken(token)
        return if (response["status"] == "ok") {
            Result.success(User(response["user_id"] as Int))
        } else {
            Result.failure(AuthException("Login failed"))
        }
    }
}

LegacyAuthAdapter mengubah panggilan login(credentials) menjadi loginWithToken(token) untuk API lama. Klien (ViewModel) bekerja melalui antarmuka AuthService dan tidak tahu apakah di bawahnya ada Firebase Auth terbaru atau API lama berusia sepuluh tahun. Ini memungkinkan penggantian implementasi tanpa mengubah kode klien.

Adapter di Android: RecyclerView dan ListAdapter

RecyclerView.Adapter — implementasi paling umum dari pola Adapter di Android. Ia mengubah data (daftar objek) menjadi ViewHolder yang ditampilkan RecyclerView di layar. Dengan munculnya ListAdapter (Android Architecture Components), pola tersebut mendapat dukungan bawaan untuk perhitungan diff untuk animasi perubahan.

Kotlin
class UserAdapter(
    private val onItemClick: (User) -> Unit
) : ListAdapter(DiffCallback()) {

    override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): UserViewHolder {
        val view = LayoutInflater.from(parent.context)
            .inflate(R.layout.item_user, parent, false)
        return UserViewHolder(view)
    }

    override fun onBindViewHolder(
        holder: UserViewHolder,
        position: Int
    ) {
        holder.bind(getItem(position), onItemClick)
    }

    class UserViewHolder(itemView: View) :
        RecyclerView.ViewHolder(itemView) {
        
        private val tvName = itemView.findViewById(R.id.tvName)
        
        fun bind(user: User, click: (User) -> Unit) {
            tvName.text = user.name
            itemView.setOnClickListener { click(user) }
        }
    }

    private class DiffCallback : DiffUtil.ItemCallback() {
        override fun areItemsTheSame(old: User, new: User) = old.id == new.id
        override fun areContentsTheSame(old: User, new: User) = old == new
    }
}

UserAdapter menggunakan ListAdapter dengan DiffUtil untuk menggambar ulang daftar secara efisien. Saat data diperbarui, DiffCallback menghitung perbedaan antara daftar lama dan baru, dan RecyclerView hanya menganimasikan elemen yang berubah — tanpa menggambar ulang seluruh daftar. Ini adalah keunggulan utama dibandingkan ListView lama yang memerlukan notifyDataSetChanged() manual.

Adapter di iOS: UITableView dan DiffableDataSource

UITableViewDataSource — adalah pola Adapter dan DataSource sekaligus. Ia mengubah data model menjadi sel tabel. Sejak iOS 13, Apple memperkenalkan DiffableDataSource — pengganti modern yang, seperti ListAdapter di Android, secara otomatis menghitung perubahan dan menganimasikan pembaruan.

Swift
class UserTableViewAdapter: NSObject, UITableViewDataSource {
    var items: [User] = []
    
    func tableView(_ tableView: UITableView,
                    numberOfRowsInSection section: Int) -> Int {
        items.count
    }
    
    func tableView(_ tableView: UITableView,
                    cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(
            withIdentifier: "UserCell", for: indexPath)
        let user = items[indexPath.row]
        cell.textLabel?.text = user.name
        return cell
    }
}

// Versi modern: DiffableDataSource
enum Section { case main }

class ModernUserAdapter {
    var dataSource: UITableViewDiffableDataSource<Section, User>!
    
    func configure(for tableView: UITableView) {
        dataSource = UITableViewDiffableDataSource(
            tableView: tableView
        ) { tableView, indexPath, user in
            let cell = tableView.dequeueReusableCell(
                withIdentifier: "UserCell", for: indexPath)
            cell.textLabel?.text = user.name
            return cell
        }
    }
    
    func update(with users: [User]) {
        var snapshot = NSDiffableDataSourceSnapshot<Section, User>()
        snapshot.appendSections([.main])
        snapshot.appendItems(users)
        dataSource.apply(snapshot, animatingDifferences: true)
    }
}

ModernUserAdapter dengan DiffableDataSource secara otomatis menganimasikan perubahan saat data diperbarui: elemen muncul, menghilang, atau berpindah dengan animasi yang halus. DiffableDataSource iOS dan ListAdapter Android menyelesaikan tugas yang sama dengan API berbeda, tetapi dengan logika yang sama — perhitungan diff + animasi otomatis.

Object Adapter vs Class Adapter

Object Adapter menggunakan komposisi: adapter berisi referensi ke objek Adaptee dan mendelegasikan panggilan kepadanya. Class Adapter menggunakan pewarisan: adapter mewarisi Adaptee dan secara bersamaan mengimplementasikan antarmuka target. Di Java, Swift, dan Kotlin, Class Adapter tidak mungkin karena tidak adanya pewarisan berganda — hanya Object Adapter yang tersisa.

KarakteristikObject AdapterClass Adapter
MekanismeKomposisi (berisi Adaptee)Pewarisan (extends Adaptee)
FleksibilitasLebih tinggi — Adaptee dapat diubah saat runtimeLebih rendah — Adaptee tetap saat kompilasi
KeterikatanLemah (melalui antarmuka)Kuat (melalui pewarisan)
Adaptasi subkelasYa — Adaptee bisa berupa subkelas apa punTidak — hanya superkelas konkret
KetersediaanJava, Kotlin, Swift, C++, C#Hanya bahasa dengan pewarisan berganda (C++)

Dalam pengembangan mobile, hanya Object Adapter yang digunakan. RecyclerView.Adapter berisi referensi ke data dan LayoutInflater, UITableViewDataSource berisi array elemen. Komposisi membuat kode lebih fleksibel dan mudah diuji dibandingkan dengan pewarisan.

Contoh Adapter di proyek nyata

Adapter tidak hanya diterapkan untuk daftar. Mari kita lihat tiga skenario dari praktik pengembangan mobile di mana pola tersebut memecahkan masalah integrasi komponen yang tidak kompatibel.

SkenarioAdapteeTargetAdapter
Integrasi pustaka auth lamaLegacyAuthLib (callback-based)AuthService (suspend)LegacyAuthAdapter
Adaptasi JSON ke model baruGsonParserJsonParser (Kotlinx Serialization)GsonAdapter
Antarmuka seragam untuk layanan pushFCM, APNs, Huawei PushPushService token registerPushServiceAdapter

Setiap Adapter mengenkapsulasi logika transformasi: GsonAdapter menerjemahkan string JSON menjadi objek melalui @SerializedName, PushServiceAdapter mengabstraksi pendaftaran token untuk berbagai platform. Klien (logika bisnis) bekerja dengan antarmuka seragam dan tidak bergantung pada implementasi tertentu.

Kesalahan umum saat mengimplementasikan Adapter

Kesalahan dalam implementasi Adapter menyebabkan daftar melambat, kebocoran memori, dan bug pembaruan data. Mari kita bahas tiga masalah umum.

Operasi berat di onBindViewHolder

onBindViewHolder dipanggil untuk setiap sel saat scrolling. Pembuatan objek, parsing JSON, atau query database di metode ini menyebabkan daftar tersendat (frame drops). Solusi: lakukan semua perhitungan berat sebelumnya, berikan data yang sudah siap ke adapter. Untuk gambar, gunakan pustaka dengan caching — Glide, Coil, Kingfisher.

Mengabaikan DiffUtil / DiffableDataSource

Memanggil notifyDataSetChanged() pada setiap pembaruan menggambar ulang seluruh daftar, menyebabkan kedipan dan kehilangan fokus pada input. Solusi: gunakan ListAdapter dengan DiffUtil di Android atau DiffableDataSource di iOS. Perhitungan diff memakan waktu <1 ms untuk daftar hingga 1000 elemen dan memastikan animasi yang halus.

Menyimpan objek berat di adapter

Adapter hidup selama RecyclerView/UITableView. Menyimpan Bitmap atau array besar di adapter menyebabkan kebocoran memori saat perubahan konfigurasi (rotasi layar, perubahan tema). Solusi: adapter harus menyimpan hanya model data ringan (data class / struct), dan memuat sumber daya berat melalui ViewHolder sesuai permintaan.

Pertanyaan yang Sering Diajukan

Apa perbedaan antara Adapter dan Proxy?

Adapter mengubah antarmuka Adaptee menjadi antarmuka Target — klien mendapatkan cara interaksi baru. Proxy menyediakan antarmuka yang sama dengan objek asli, tetapi menambahkan kontrol akses, caching, atau inisialisasi malas. Proxy tidak mengubah antarmuka, Adapter — mengubah.

Mengapa RecyclerView.Adapter adalah contoh pola Adapter?

RecyclerView.Adapter mengubah data (misalnya, daftar User) menjadi ViewHolder yang dapat ditampilkan RecyclerView. RecyclerView mengharapkan ViewHolder, data dalam format List<User> — Adapter menyesuaikan satu dengan yang lain. Selain itu, Adapter mengelola siklus hidup ViewHolder melalui recycle pool, meningkatkan kinerja daftar.

Apa perbedaan antara Object Adapter dan Class Adapter?

Object Adapter menggunakan komposisi: berisi referensi ke Adaptee dan mendelegasikan panggilan kepadanya. Class Adapter menggunakan pewarisan berganda: mewarisi Adaptee dan mengimplementasikan Target. Di Java, Kotlin, dan Swift, hanya Object Adapter yang tersedia karena tidak adanya pewarisan berganda kelas. Class Adapter hanya mungkin di C++.

Kapan menggunakan Adapter daripada Facade?

Adapter digunakan ketika dua kelas yang ada perlu bekerja sama dengan mengubah antarmuka salah satunya. Facade — ketika interaksi dengan subsistem kompleks perlu disederhanakan dengan menyediakan antarmuka sederhana. Adapter — untuk kompatibilitas, Facade — untuk penyederhanaan.

Bisakah Adapter diimplementasikan tanpa antarmuka?

Ya, menggunakan penutupan (closures). Alih-alih antarmuka dengan satu metode, fungsi dapat diteruskan. Misalnya, di Swift: let adapter = { (data: Data) -> [CellConfig] in /* transformasi */ }. Pendekatan ini disebut functional adapter. Namun untuk 2+ metode, protokol/antarmuka tetap lebih disukai — membuat kontrak menjadi eksplisit.

Kesimpulan

  • Adapter — pola struktural yang mengubah antarmuka Adaptee yang tidak kompatibel menjadi Target melalui kelas perantara
  • RecyclerView.Adapter (Android) dan UITableViewDataSource (iOS) — contoh utama pola dalam pengembangan mobile
  • Object Adapter menggunakan komposisi; Class Adapter (hanya C++) — pewarisan berganda
  • ListAdapter + DiffUtil (Android) dan DiffableDataSource (iOS) — evolusi modern dengan diff otomatis dan animasi
  • Operasi berat di onBindViewHolder, mengabaikan DiffUtil, dan menyimpan sumber daya di adapter — kesalahan umum
  • Adapter diterapkan untuk integrasi kode lama, adaptasi format, dan unifikasi berbagai implementasi
  • Rekomendasi: gunakan ListAdapter/DiffableDataSource alih-alih pengelolaan pembaruan daftar secara manual

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.

Diskusikan proyek

Baca juga