Adapter — یہ کیا ہے، موبائل ڈیولپمنٹ کے لیے انٹرفیس تبدیلی کا پیٹرن

مصنف: IT Sectr اشاعت: 2026-02-18 مطالعے کا وقت: 10 منٹ

Adapter ایک ساختی ڈیزائن پیٹرن ہے جو ایک کلاس کے انٹرفیس کو دوسرے انٹرفیس میں تبدیل کرتا ہے جس کی کلائنٹ توقع کرتا ہے۔ موبائل ڈیولپمنٹ میں، Adapter سب سے زیادہ Android میں RecyclerView.Adapter اور iOS میں UITableViewDataSource کے طور پر استعمال ہوتا ہے۔ Google I/O (2024) کے مطابق، RecyclerView 95% Android ایپس میں فہرستوں کو ظاہر کرنے کے لیے استعمال ہوتا ہے، اور ہر ایک کو اپنے Adapter کے نفاذ کی ضرورت ہوتی ہے۔

اہم نکات

  • Adapter ایک ساختی پیٹرن ہے جو غیر مطابقت پذیر انٹرفیس والی اشیاء کو ایک ساتھ کام کرنے کی اجازت دیتا ہے
  • RecyclerView.Adapter Android میں پیٹرن کا نفاذ ہے، جو ڈیٹا کو فہرست کے لیے ViewHolders میں تبدیل کرتا ہے
  • UITableViewDataSource iOS میں نفاذ ہے، جو Adapter اور DataSource پیٹرن کو یکجا کرتا ہے
  • Object Adapter کمپوزیشن استعمال کرتا ہے: اڈاپٹر میں اڈاپٹی آبجیکٹ کا حوالہ ہوتا ہے
  • Class Adapter متعدد وراثت استعمال کرتا ہے — صرف C++ میں ممکن، Java/Swift/Kotlin میں دستیاب نہیں

Adapter پیٹرن کیا ہے؟

Adapter ایک ساختی پیٹرن ہے جو انٹرفیس کی عدم مطابقت کے مسئلے کو حل کرتا ہے۔ یہ ایک آبجیکٹ (Adaptee) کو ایک کلاس (Adapter) میں لپیٹتا ہے جس میں کلائنٹ کا متوقع انٹرفیس (Target) ہوتا ہے۔ کلائنٹ Target کے ساتھ کام کرتا ہے اور Adaptee کے وجود سے آگاہ نہیں ہوتا۔ یہ Wrapper پیٹرن کی ایک قسم ہے۔

Kotlin
// غیر مطابقت پذیر انٹرفیس والی موجودہ کلاس
class LegacyAuthApi {
    fun loginWithToken(token: String): Map {
        return mapOf("status" to "ok", "user_id" to 42)
    }
}

// ہدف انٹرفیس (کلائنٹ کیا توقع کرتا ہے)
interface AuthService {
    suspend fun login(credentials: Credentials): Result
}

// Adapter — LegacyAuthApi کو 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 پرانی API کے لیے login(credentials) کال کو loginWithToken(token) میں تبدیل کرتا ہے۔ کلائنٹ (ViewModel) AuthService انٹرفیس کے ذریعے کام کرتا ہے اور نہیں جانتا کہ اس کے نیچے تازہ ترین Firebase Auth ہے یا دہائیوں پرانی لیگیسی API۔ یہ کلائنٹ کوڈ کو تبدیل کیے بغیر نفاذ کو تبدیل کرنے کی اجازت دیتا ہے۔

Android میں Adapter: RecyclerView اور ListAdapter

RecyclerView.Adapter Android میں Adapter پیٹرن کا سب سے عام نفاذ ہے۔ یہ ڈیٹا (اشیاء کی فہرست) کو ViewHolders میں تبدیل کرتا ہے جو RecyclerView اسکرین پر ظاہر کرتا ہے۔ ListAdapter (Android Architecture Components) کے متعارف ہونے کے ساتھ، پیٹرن کو تبدیلیوں کو متحرک کرنے کے لیے بلٹ ان فرق حساب کتاب کی مدد ملی۔

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 موثر فہرست دوبارہ ڈرائنگ کے لیے DiffUtil کے ساتھ ListAdapter استعمال کرتا ہے۔ جب ڈیٹا اپ ڈیٹ ہوتا ہے، DiffCallback پرانی اور نئی فہرست کے درمیان فرق کا حساب لگاتا ہے، اور RecyclerView صرف تبدیل شدہ آئٹمز کو متحرک کرتا ہے — پوری فہرست کو دوبارہ ڈرائنگ کیے بغیر۔ یہ پرانی ListView کے مقابلے میں ایک اہم فائدہ ہے، جس کے لیے دستی notifyDataSetChanged() کی ضرورت تھی۔

iOS میں Adapter: UITableView اور DiffableDataSource

UITableViewDataSource ایک ساتھ Adapter پیٹرن اور DataSource پیٹرن دونوں ہے۔ یہ ماڈل ڈیٹا کو ٹیبل سیلز میں تبدیل کرتا ہے۔ iOS 13 سے، Apple نے DiffableDataSource متعارف کرایا — ایک جدید متبادل، جو Android میں ListAdapter کی طرح، خود بخود تبدیلیوں کا حساب لگاتا ہے اور اپ ڈیٹس کو متحرک کرتا ہے۔

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
    }
}

// جدید ورژن: 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 DiffableDataSource کے ساتھ ڈیٹا اپ ڈیٹ ہونے پر خود بخود تبدیلیوں کو متحرک کرتا ہے: آئٹمز ہموار اینیمیشن کے ساتھ ظاہر، غائب یا منتقل ہوتے ہیں۔ iOS کا DiffableDataSource اور Android کا ListAdapter مختلف APIs سے ایک ہی مسئلہ حل کرتے ہیں لیکن ایک ہی منطق سے — فرق حساب + خودکار اینیمیشن۔

Object Adapter بمقابلہ Class Adapter

Object Adapter کمپوزیشن استعمال کرتا ہے: اڈاپٹر میں Adaptee آبجیکٹ کا حوالہ ہوتا ہے اور اسے کالز تفویض کرتا ہے۔ Class Adapter وراثت استعمال کرتا ہے: اڈاپٹر Adaptee سے وراثت پاتا ہے اور بیک وقت ہدف انٹرفیس کو لاگو کرتا ہے۔ Java، Swift اور Kotlin میں، متعدد وراثت کی کمی کی وجہ سے Class Adapter ناممکن ہے — صرف Object Adapter رہ جاتا ہے۔

خصوصیتObject AdapterClass Adapter
میکانزمکمپوزیشن (Adaptee پر مشتمل)وراثت (Adaptee کو بڑھاتا ہے)
لچکزیادہ — Adaptee کو رن ٹائم پر تبدیل کیا جا سکتا ہےکم — Adaptee کمپائل ٹائم پر مقرر
وابستگیکمزور (انٹرفیس کے ذریعے)مضبوط (وراثت کے ذریعے)
ذیلی کلاس موافقتہاں — Adaptee کوئی بھی ذیلی کلاس ہو سکتی ہےنہیں — صرف مخصوص سپرکلاس
دستیابیJava, Kotlin, Swift, C++, C#صرف متعدد وراثت والی زبانیں (C++)

موبائل ڈیولپمنٹ میں، صرف Object Adapter استعمال ہوتا ہے۔ RecyclerView.Adapter میں ڈیٹا اور LayoutInflater کے حوالے ہوتے ہیں، UITableViewDataSource میں آئٹمز کی ایک صف ہوتی ہے۔ کمپوزیشن وراثت کے مقابلے میں کوڈ کو زیادہ لچکدار اور قابل جانچ بناتی ہے۔

حقیقی منصوبوں میں Adapter کی مثالیں

Adapter صرف فہرستوں کے لیے استعمال نہیں ہوتا۔ آئیے موبائل ڈیولپمنٹ پریکٹس سے تین منظرناموں پر غور کریں جہاں پیٹرن غیر مطابقت پذیر اجزاء کو ضم کرنے کا مسئلہ حل کرتا ہے۔

منظرAdapteeTargetAdapter
پرانی تصدیقی لائبریری کا انضمامLegacyAuthLib (کال بیک پر مبنی)AuthService (suspend)LegacyAuthAdapter
نئے ماڈل کے لیے JSON کی موافقتGsonParserJsonParser (Kotlinx Serialization)GsonAdapter
پش سروسز کے لیے متحد انٹرفیسFCM, APNs, Huawei PushPushService token registerPushServiceAdapter

ہر Adapter تبدیلی کی منطق کو انکیپسلیٹ کرتا ہے: GsonAdapter @SerializedName کے ذریعے JSON سٹرنگ کو آبجیکٹ میں ترجمہ کرتا ہے، PushServiceAdapter مختلف پلیٹ فارمز کے لیے ٹوکن رجسٹریشن کو خلاصہ کرتا ہے۔ کلائنٹ (کاروباری منطق) متحد انٹرفیس کے ساتھ کام کرتا ہے اور مخصوص نفاذ پر منحصر نہیں ہوتا۔

Adapter لاگو کرتے وقت عام غلطیاں

Adapter کے نفاذ میں غلطیاں فہرست کی سستی، میموری لیک اور ڈیٹا اپ ڈیٹ میں خرابیوں کا باعث بنتی ہیں۔ آئیے تین عام مسائل پر غور کریں۔

onBindViewHolder میں بھاری کارروائیاں

onBindViewHolder اسکرولنگ کے دوران ہر سیل کے لیے کہا جاتا ہے۔ اس طریقہ میں آبجیکٹ بنانا، JSON تجزیہ کرنا یا ڈیٹابیس کو کال کرنا فریم ڈراپ کا سبب بنتا ہے۔ حل: تمام بھاری حسابات پہلے سے کریں، اڈاپٹر کو تیار ڈیٹا پاس کریں۔ تصاویر کے لیے کیشنگ لائبریریاں استعمال کریں — Glide، Coil، Kingfisher۔

DiffUtil / DiffableDataSource کو نظر انداز کرنا

ہر اپ ڈیٹ پر notifyDataSetChanged() کو کال کرنا پوری فہرست کو دوبارہ کھینچتا ہے، جس سے جھلملاہٹ اور ان پٹ پر فوکس کا نقصان ہوتا ہے۔ حل: Android میں DiffUtil کے ساتھ ListAdapter یا iOS میں DiffableDataSource استعمال کریں۔ فرق حساب میں 1000 آئٹمز تک کی فہرستوں کے لیے <1 ms لگتا ہے اور ہموار اینیمیشن کو یقینی بناتا ہے۔

اڈاپٹر میں بھاری اشیاء ذخیرہ کرنا

اڈاپٹر اس وقت تک زندہ رہتا ہے جب تک RecyclerView/UITableView۔ اڈاپٹر میں Bitmap یا بڑی صفیں ذخیرہ کرنا کنفیگریشن تبدیلیوں (اسکرین گھومنے، تھیم تبدیل کرنے) پر میموری لیک کا سبب بنتا ہے۔ حل: اڈاپٹر کو صرف ہلکے ڈیٹا ماڈل (data class / struct) ذخیرہ کرنے چاہئیں، اور بھاری وسائل کو ضرورت پر ViewHolder کے ذریعے لوڈ کرنا چاہیے۔

اکثر پوچھے گئے سوالات

Adapter اور Proxy میں کیا فرق ہے؟

Adapter Adaptee انٹرفیس کو Target انٹرفیس میں تبدیل کرتا ہے — کلائنٹ کو تعامل کا ایک نیا طریقہ ملتا ہے۔ Proxy اصل آبجیکٹ جیسا ہی انٹرفیس فراہم کرتا ہے، لیکن رسائی کنٹرول، کیشنگ یا سست ابتدا کا اضافہ کرتا ہے۔ Proxy انٹرفیس نہیں بدلتا، Adapter بدلتا ہے۔

RecyclerView.Adapter Adapter پیٹرن کی مثال کیوں ہے؟

RecyclerView.Adapter ڈیٹا (مثلاً، User کی فہرست) کو ViewHolder میں تبدیل کرتا ہے جسے RecyclerView ظاہر کر سکتا ہے۔ RecyclerView ViewHolder کی توقع کرتا ہے، ڈیٹا List<User> فارمیٹ میں ہے — Adapter ایک کو دوسرے کے مطابق ڈھالتا ہے۔ مزید برآں، Adapter ری سائیکل پول کے ذریعے ViewHolder لائف سائیکل کا انتظام کرتا ہے، فہرست کی کارکردگی کو بہتر بناتا ہے۔

Object Adapter اور Class Adapter میں کیا فرق ہے؟

Object Adapter کمپوزیشن استعمال کرتا ہے: اس میں Adaptee کا حوالہ ہوتا ہے اور اسے کالز تفویض کرتا ہے۔ Class Adapter متعدد وراثت استعمال کرتا ہے: یہ Adaptee سے وراثت پاتا ہے اور Target کو لاگو کرتا ہے۔ Java، Kotlin اور Swift میں، متعدد کلاس وراثت کی کمی کی وجہ سے صرف Object Adapter دستیاب ہے۔ Class Adapter صرف C++ میں ممکن ہے۔

Facade کی بجائے Adapter کب استعمال کریں؟

Adapter اس وقت استعمال ہوتا ہے جب آپ کو دو موجودہ کلاسوں کو ایک ساتھ کام کرنے کی ضرورت ہو، ان میں سے ایک کے انٹرفیس کو تبدیل کرکے۔ Facade اس وقت استعمال ہوتا ہے جب آپ کو ایک سادہ انٹرفیس فراہم کرکے ایک پیچیدہ ذیلی نظام کے ساتھ تعامل کو آسان بنانے کی ضرورت ہو۔ Adapter مطابقت کے لیے، Facade آسان بنانے کے لیے۔

کیا Adapter بغیر انٹرفیس کے لاگو کیا جا سکتا ہے؟

ہاں، closure استعمال کرکے۔ ایک طریقہ والے انٹرفیس کے بجائے، ایک فنکشن پاس کیا جا سکتا ہے۔ مثال کے طور پر، Swift میں: let adapter = { (data: Data) -> [CellConfig] in /* تبدیلی */ }۔ اس نقطہ نظر کو فنکشنل اڈاپٹر کہا جاتا ہے۔ تاہم، 2+ طریقوں کے لیے، پروٹوکول/انٹرفیس ترجیحی رہتا ہے — یہ معاہدے کو واضح کرتا ہے۔

خلاصہ

  • Adapter ایک ساختی پیٹرن ہے جو غیر مطابقت پذیر Adaptee انٹرفیس کو ایک درمیانی کلاس کے ذریعے Target میں تبدیل کرتا ہے
  • RecyclerView.Adapter (Android) اور UITableViewDataSource (iOS) موبائل ڈیولپمنٹ میں پیٹرن کی اہم مثالیں ہیں
  • Object Adapter کمپوزیشن استعمال کرتا ہے؛ Class Adapter (صرف C++) متعدد وراثت استعمال کرتا ہے
  • ListAdapter + DiffUtil (Android) اور DiffableDataSource (iOS) خودکار فرق اور اینیمیشن کے ساتھ جدید ارتقا ہیں
  • onBindViewHolder میں بھاری کارروائیاں، DiffUtil کو نظر انداز کرنا اور اڈاپٹر میں وسائل ذخیرہ کرنا عام غلطیاں ہیں
  • Adapter لیگیسی کوڈ انضمام، فارمیٹ موافقت اور مختلف نفاذات کو یکجا کرنے کے لیے استعمال ہوتا ہے
  • سفارش: دستی فہرست اپ ڈیٹ مینجمنٹ کے بجائے ListAdapter/DiffableDataSource استعمال کریں

ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے

IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔

پروجیکٹ پر بحث کریں

مزید پڑھیں