Callback — bu nima, qayta chaqiruv funksiyalari va qanday ishlaydi

Muallif: IT Sectr Nashr etilgan: 2026-03-17 O'qish vaqti: 11 daq

Callback — bu asinxron operatsiya tugagandan so'ng bajarilish uchun boshqa funksiyaga argument sifatida uzatiladigan funksiyadir. Mobil ishlanmada callback tarmoq so'rovlari natijalarini qayta ishlash, ma'lumotlar bazalari bilan ishlash va animatsiyalar uchun qo'llaniladi. Apple Documentation (2025) ma'lumotiga ko'ra, Swift-dagi closure'lar callback-ning asosiy shaklidir va URLSession, GCD va Combine-da ishlatiladi. Android-da callback interfeyslar, Kotlin lambda ifodalari va ListenableFuture orqali amalga oshiriladi.

Asosiy ma'lumotlar

  • Callback — asinxron bajarish uchun argument sifatida uzatiladigan qayta chaqiruv funksiyasi.
  • Swift callback uchun @escaping kalit so'zi bilan closure'lardan foydalanadi.
  • Kotlin callback uchun lambda ifodalari va yuqori darajali funksiyalarni qo'llaydi.
  • Retain cycle — iOS-da callback-da self-ni tutishda xotira oqishi.
  • Callback Hell — async/await va korutinlar orqali hal qilinadigan ichma-ich callback muammosi.

Callback nima?

Callback (qayta chaqiruv funksiyasi) — bu boshqa funksiyaga uzatiladigan va ma'lum bir harakat tugagandan so'ng chaqiriladigan bajariladigan kod. Mobil ishlanmada callback asinxron dasturlashning asosiy mexanizmi bo'lib, asosiy oqimni bloklamasdan tarmoq so'rovlari, taymerlar, animatsiyalar va kiritish-chiqarish operatsiyalarining tugashiga reaksiya berishga imkon beradi. Swift va Kotlin callback yaratish uchun o'rnatilgan sintaktik konstruksiyalarni taqdim etadi — mos ravishda closure'lar va lambdalar.

Callback-ning ishlash prinsipi

Yuqori darajali funksiya boshqa funksiyani parametr sifatida qabul qiladi va o'zining asosiy mantiqini bajarganidan so'ng uni chaqiradi. Boshqaruv oqimi callback orqali chaqiruvchiga qaytariladi, nomi ham shundan kelib chiqqan. iOS-da callback UIKit (UIView.animate animatsiyalari), Foundation (URLSession.dataTask) va Combine (sink) da qo'llaniladi. Android-da callback View.OnClickListener, Retrofit Callback va Room DAO da ishlatiladi. Zamonaviy API-lar tobora ko'proq callback-ni async/await yoki korutinlar bilan almashtirmoqda, ammo callback-ni tushunish legacy kod va past darajali API-lar bilan ishlash uchun zarur.

Sinxron va asinxron Callback

Callback sinxron (funksiya ichida darhol chaqiriladigan) va asinxron (keyinroq boshqa oqim yoki navbatdan chaqiriladigan) bo'lishi mumkin. Sinxron callback'lar saralash (komparatorlar) va kolleksiyalarni aylanib o'tish uchun ishlatiladi. Asinxron callback'lar tarmoq so'rovlari, fayllarni o'qish va sensorlar bilan ishlash uchun qo'llaniladi. Farq threading-ni tushunish uchun muhim: sinxron callback bir xil oqimda bajariladi, asinxron — dispetcher tomonidan belgilangan oqimda (iOS-da DispatchQueue, Kotlin-da Dispatchers).

Callback iOS va Android-da qanday ishlaydi?

Ikkala platformada callback mexanizmi bir xil printsipga asoslanadi: funksiya birinchi darajali obyekt sifatida uzatiladi va bajarish vaqtigacha saqlanadi. Biroq, amalga oshirishlar turli til paradigmalari tufayli farqlanadi. iOS-da callback — atrofdagi kontekstdan o'zgaruvchilarni tutuvchi closure'dir. Android-da callback ko'pincha anonim sinflar yoki FunctionalInterface-ga kompilyatsiya qilinadigan Kotlin lambda ifodalari orqali amalga oshiriladi.

iOS-da Callback-ning hayot aylanishi

Asinxron funksiya chaqirilganda, closure olingan o'zgaruvchilar bilan birga yig'imda saqlanadi. Operatsiya tugagach, GCD yoki OperationQueue tizimi callback-ni tegishli navbatga (main queue yoki background queue) joylashtiradi. Bajarilgandan so'ng, kuchli havolalar bo'lmaganda callback xotiradan o'chiriladi. Capture list ([weak self]) obyektning deallokatsiyadan keyin saqlanishining oldini oladi. Capture list bo'lmasa, retain cycle yuzaga keladi, bunda obyekt va callback bir-biriga havola qiladi.

swift
func fetchData(completion: @escaping (Result<Data, Error>) -> Void) {
    let task = URLSession.shared.dataTask(with: url) { data, response, error in
        if let error = error {
            completion(.failure(error))
            return
        }
        completion(.success(data))
    }
    task.resume()
}

// [weak self] bilan foydalanish
fetchData { [weak self] result in
    guard let self else { return }
    switch result {
    case .success(let data):
        self.updateUI(data)
    case .failure(let error):
        self.showError(error)
    }
}

Android-da Callback-ning hayot aylanishi

Android-da callback interfeys yoki lambda orqali uzatiladi. ExecutorService yoki korutin orqali asinxron operatsiya bajarilganda, callback fon ishi tugaguncha xotirada saqlanadi. Kotlin lambdalari tashqi o'zgaruvchilarni tutuvchi anonim sinflarga kompilyatsiya qilinadi. JVM-da zaif havolalarning yo'qligi qo'lda boshqarishni talab qiladi: onDestroy() da callback-ni nolga tenglashtirish yoki Job.cancel() orqali korutinlarni bekor qilish. ViewModel va LiveData bu muammoni arxitektura komponenti darajasida hal qiladi.

kotlin
interface Callback<T> {
    fun onSuccess(data: T)
    fun onError(error: Throwable)
}

class Repository {
    fun loadData(callback: Callback<List<User>>) {
        thread {
            try {
                val result = api.fetchUsers()
                runOnUiThread { callback.onSuccess(result) }
            } catch (e: Exception) {
                runOnUiThread { callback.onError(e) }
            }
        }
    }
}

// Lambda bilan foydalanish
repository.loadData(object : Callback<List<User>> {
    override fun onSuccess(data: List<User>) { showUsers(data) }
    override fun onError(error: Throwable) { showError(error.message) }
})

Swift va Kotlin-da Callback sintaksisi

Callback sintaksisi funksiyalar bilan birinchi darajali obyektlar sifatida ishlash uchun til imkoniyatlari bilan belgilanadi. Swift-da closure'lar avtomatik argument nomlari ($0, $1) bilan qisqa sintaksisga ega. Kotlin-da lambdalar ham bitta argument uchun it-ni qo'llab-quvvatlaydi. Farqlar o'zgaruvchilarni tutish (Swift-da capture list vs Kotlin-da o'zgartiriladigan havolalar) va tipizatsiyada (Result<Success, Failure> vs Result<T>) namoyon bo'ladi.

Swift-da Callback: closure'lar

Swift closure-i — bu o'zini-o'zi ta'minlaydigan kod bloki bo'lib, boshqa funksiyaga uzatilishi va ishlatilishi mumkin. Closure'lar global (nomlangan), ichma-ich va expression-level bo'lishi mumkin. @escaping funksiyadan qaytganidan keyin bajariladigan closure-ni belgilaydi — bu asinxron callback'lar uchun majburiy talabdir. @escaping bo'lmasa, closure faqat funksiya tanasi ichida bajarilishi mumkin. Trailing closure syntax closure-ni dumaloq qavslardan keyin uzatishga imkon beradi: fetchData { result in ... }.

swift
typealias NetworkResult = (Result<[String: Any], Error>) -> Void

func performRequest(
    url: URL,
    then handler: @escaping NetworkResult
) {
    let task = URLSession.shared.dataTask(with: url) { data, _, error in
        handler(Result {
            guard let json = try JSONSerialization.jsonObject(with: data)
            else { throw NetworkError.invalidData }
            return json as! [String: Any]
        })
    }
    task.resume()
}

performRequest(url: url) { result in
    switch result {
    case .success(let json): process(json)
    case .failure(let error): log(error.localizedDescription)
    }
}

Kotlin-da Callback: lambdalar va yuqori darajali funksiyalar

Kotlin boshqa funksiyalarni parametr sifatida qabul qiluvchi yuqori darajali funksiyalarni qo'llab-quvvatlaydi. Callback Kotlin-da (T) -> Unit yoki qaytariladigan qiymat uchun (T) -> R tipidagi parametr orqali uzatiladi. Kotlin korutinlarining suspend funksiyalari callback-ni ketma-ket kod bilan almashtiradi, ammo callback Java-ga mos API va Android SDK-da (View.setOnClickListener, TextWatcher) qoladi. Kotlin lambdalari avtomatik ravishda val o'zgaruvchilarni tutadi, var o'zgaruvchilari o'zgartiriladigan o'ramlarni talab qiladi.

kotlin
fun <T, R> processWithCallback(
    input: T,
    transform: (T) -> R,
    onResult: (R) -> Unit
) {
    thread {
        val result = transform(input)
        runOnUiThread { onResult(result) }
    }
}

// Lambda bilan misol
processWithCallback(
    input = "Hello",
    transform = { it.length },
    onResult = { length ->
        textView.text = "Length: $length"
    }
)

Retain cycles va Callback-da xotira oqishlari

Retain cycle — ikki obyekt bir-biriga kuchli havolalarni saqlab, xotirani bo'shatishga to'sqinlik qiladigan holat. Swift-da retain cycle viewController closure-ni tutganda va closure self-ni tutganda yuzaga keladi. Kotlin/Java-da Activity ichki sinf yoki lambda-ni uzoq muddatli fon operatsiyasiga uzatganda oqish yuz beradi. WWDC Session 10216 (2024) ma'lumotiga ko'ra, closure-larni noto'g'ri boshqarish iOS ilovalarida xotira oqishlarining uchinchi eng keng tarqalgan sababidir.

Swift-da Retain cycles

Swift havolalar hisoblagichi nolga tushganda obyektni bo'shatadigan Automatic Reference Counting (ARC) dan foydalanadi. Closure-da Capture list [weak self] yoki [unowned self] retain cycle-ning oldini oladi. weak self obyektning deallokatsiyasida nil bo'ladigan ixtiyoriy havola yaratadi. unowned self closure-dan uzoqroq yashaydi deb taxmin qiladi — bu taxmin buzilsa, crash yuz beradi. Xavfsiz standart variant sifatida weak self dan foydalanish tavsiya etiladi.

swift
class DataController {
    var onDataUpdate: ((String) -> Void)?

    func setupCallback() {
        // Retain cycle!
        onDataUpdate = { text in
            self.process(text)
        }

        // Tuzatildi: [weak self]
        onDataUpdate = { [weak self] text in
            guard let self else { return }
            self.process(text)
        }
    }

    func process(_ input: String) { }
}

Android-da xotira oqishlari

Android-da callback oqishi Activity yoki Fragment tinglovchini singleton komponentga (masalan, EventBus yoki Service) uzatganda yuz beradi. WeakReference garbage collector-ga zaif havola mavjud bo'lsa ham Activity-ni bo'shatishga imkon beradi. Lifecycle-aware komponentlari (LiveData, Flow) muammoni avtomatik hal qiladi. Activity kontekstini tutuvchi Kotlin lambdalari ham oqishga sabab bo'lishi mumkin: lambda yashirincha this-ga havola saqlaydi.

kotlin
class SafeCallbackManager {
    private val listeners = mutableListOf<WeakReference<(String) -> Unit>>()

    fun addListener(callback: (String) -> Unit) {
        listeners.add(WeakReference(callback))
    }

    fun notifyAll(data: String) {
        val iterator = listeners.iterator()
        while (iterator.hasNext()) {
            val ref = iterator.next().get()
            if (ref != null) ref(data)
            else iterator.remove()
        }
    }
}

// Fragment-da foydalanish
manager.addListener { result ->
    // WeakReference Fragment-ni ushlab qolmaydi
    updateUI(result)
}

Callback Hell va kurashish usullari

Callback Hell (shuningdek, Halokat Piramidasi sifatida ham tanilgan) — ko'plab ichma-ich callback'lar o'qish va tuzatish qiyin bo'lgan chuqur ichma-ich kod strukturasini yaratadigan holat. Har bir keyingi qadam avvalgisining tugashini kutishni talab qiladi, bu esa 5-10 darajali ichma-ichlikka olib keladi. Bu muammo ketma-ket asinxron operatsiyalar uchun xarakterlidir: ma'lumot yuklash → tahlil qilish → ma'lumotlar bazasiga saqlash → UI yangilash.

Swift-da yechimlar: async/await

Swift 5.5 asinxron kodni ketma-ket yozishga imkon beruvchi asinxron funksiyalar (async/await) ni taqdim etdi. AsyncSequence va AsyncStream callback-ga asoslangan iteratsiyalarni almashtiradi. Combine framework-i ichma-ichliksiz asinxron oqimlarni kompozitsiya qilish uchun flatMap, merge, combineLatest operatorlarini taqdim etadi. Biroq, callback Objective-C API va async qo'llab-quvvatlamaydigan uchinchi tomon kutubxonalari bilan ishlash uchun zarur bo'lib qoladi.

swift
// Ichma-ich callback — Callback Hell
loginUser(credentials) { user in
    fetchProfile(user.id) { profile in
        downloadAvatar(profile.avatarUrl) { image in
            cacheImage(image) { success in
                updateUI(user, profile, image)
            }
        }
    }
}

// async/await — yechim
func loadUserExperience() async throws {
    let user = try await loginUser(credentials)
    let profile = try await fetchProfile(user.id)
    let image = try await downloadAvatar(profile.avatarUrl)
    try await cacheImage(image)
    updateUI(user, profile, image)
}

Kotlin-da yechimlar: korutinlar va Flow

Kotlin korutinlari callback-ni ketma-ket bajarish bilan suspend funksiyalar bilan almashtiradi. Flow map, flatMapConcat, combine operatorlari bilan sovuq oqimlarni taqdim etadi. CoroutineScope komponent yo'q qilinganda barcha ishga tushirilgan korutinlarni bekor qilishga imkon beradi. Room, Retrofit va boshqa Jetpack kutubxonalari standart operatsiyalar uchun callback ehtiyojini bartaraf etuvchi o'rnatilgan suspend funksiya qo'llab-quvvatlashiga ega.

kotlin
// Ketma-ket callback — Callback Hell
api.login(credentials) { user ->
    api.fetchProfile(user.id) { profile ->
        api.download(profile.avatarUrl) { bytes ->
            file.save(bytes) { result ->
                textView.text = result.toString()
            }
        }
    }
}

// Korutinlar — yechim
suspend fun loadUserData() {
    val user = withContext(Dispatchers.IO) { api.login(credentials) }
    val profile = withContext(Dispatchers.IO) { api.fetchProfile(user.id) }
    val bytes = withContext(Dispatchers.IO) { api.download(profile.avatarUrl) }
    withContext(Dispatchers.IO) { file.save(bytes) }
    textView.text = "Done"
}

Callback vs Delegate: nima tanlash?

Callback va Delegate — asinxron xabardor qilishning ikki yondashuvi va ular orasidagi tanlov arxitektura talablariga bog'liq. Callback bir natijali bir martalik operatsiyalar uchun mos keladi. Delegate turli xil metod imzolari bilan ko'p sonli hodisalar uchun mo'ljallangan. Apple ko'p metodli murakkab protokollar uchun delegate-ni, bitta natijali oddiy closure'lar uchun callback-ni tavsiya qiladi. Android-da callback lambda qo'llab-quvvatlashi tufayli ko'p hollarda delegate-ni almashtiradi.

Qachon Callback-ni tanlash

Callback bitta natijali operatsiyalar uchun optimal: tarmoq so'rovi, fayl o'qish, completion bloki bilan animatsiya. Afzalliklari: ixcham sintaksis, alohida protokolning yo'qligi, kontekstning to'g'ridan-to'g'ri olinishi. Kamchiliklari: ko'p natijalarda murakkablik (taraqqiyot, pauza, bekor qilish), ko'p marta yuborishning mumkin emasligi (agar callback bir necha marta chaqirilishi mumkin bo'lsa — publisher dan foydalaning).

Qachon Delegate-ni tanlash

Delegate bir nechta majburiy va ixtiyoriy metodlarga ega protokollar uchun mos keladi: UITableViewDelegate, CLLocationManagerDelegate, Bluetooth ulanishlari. Afzalliklari: har bir metodning aniq tipizatsiyasi, protokol orqali hujjatlashtirish, @objc optional orqali ixtiyoriy metodlarni qo'llab-quvvatlash. Kamchiliklari: boilerplate kod, delegate uchun majburiy zaif havola (weak var delegate), kontekstni olishda murakkablik.

Tez-tez beriladigan savollar

Callback va yuqori darajali funksiya o'rtasidagi farq nima?

Callback yuqori darajali funksiyaning alohida holatidir. Yuqori darajali funksiya boshqa funksiyani argument sifatida qabul qiladi yoki uni qaytaradi. Callback operatsiya tugagandan so'ng asinxron bajarish uchun maxsus uzatiladigan funksiyadir. Barcha callback'lar yuqori darajali funksiyalar orqali amalga oshiriladi, lekin har bir yuqori darajali funksiya callback emas.

Callback bir necha marta chaqirilishi mumkinmi?

Kelishuvga ko'ra, callback aniq bir marta chaqirilishi kerak — success yoki failure. Bir necha marta chaqirish bir xil callback dizayn xatosi hisoblanadi. Ko'p sonli hodisalar uchun (taraqqiyot, ma'lumot oqimi) Observable, Publisher yoki Flow dan foydalaning — ular ko'p marta qiymat emissiyasini qo'llab-quvvatlaydi. Ba'zi API-lar bu qoidani buzadi, bu esa qiyin aniqlanadigan xatolarga olib keladi.

Swift-da trailing closure nima?

Trailing closure — Swift-ning sintaktik shakari bo'lib, closure-ni funksiya chaqiruvining dumaloq qavslaridan keyin uzatishga imkon beradi. Agar funksiya closure-ni oxirgi argument sifatida qabul qilsa, uni qavslardan tashqariga chiqarish mumkin: fetchData { result in ... }. Bir nechta closure'lar uchun trailing closure faqat oxirgisiga qo'llaniladi, qolganlari qavslar ichida nomlanadi. Bu callback-ga asoslangan API-larning o'qilishini yaxshilaydi.

Android-da callback-da xotira oqishidan qanday qochish mumkin?

Uzoq muddatli tinglovchilar uchun WeakReference dan foydalaning, onDestroy() da Job.cancel() orqali korutinlarni bekor qiling, avtomatik bekor qilish uchun lifecycleScope ni qo'llang. ViewModel + LiveData/Flow muammoni arxitektura darajasida hal qiladi. Statik callback'larga Activity kontekstini uzatishdan saqlaning — Application kontekstidan foydalaning. Kotlin lambdalari yashirincha this-ni tutadi, memory profiler orqali tekshiring.

Async/await callback-ni butunlay almashtiradimi?

Async/await ketma-ket asinxron kod uchun callback-ni almashtiradi, ammo event-driven arxitektura uchun emas. Callback tizim API-larida (View.OnClickListener, URLSession delegatlari), taraqqiyot bilan qayta chaqiruvlarda va uchinchi tomon kutubxonalarida qoladi. To'liq almashtirish orqaga qarab muvofiqlik tufayli mumkin emas. Zamonaviy strategiya callback o'ramlari bilan async/await dan foydalanishdir (Swift-da continuation, Kotlin-da suspendCancellableCoroutine).

Xulosa

  • Callback — operatsiya tugagandan so'ng asinxron bajarish uchun argument sifatida uzatiladigan qayta chaqiruv funksiyasi.
  • Swift callback-ni @escaping, capture list [weak self] va trailing closure sintaksisi bilan closure'lar orqali amalga oshiradi.
  • Kotlin asinxronlik uchun lambdalar, yuqori darajali funksiyalar va korutinlarning suspend funksiyalaridan foydalanadi.
  • Retain cycle iOS-da capture list bilan oldini olinadi; Android-da — WeakReference va Lifecycle-aware komponentlari bilan.
  • Callback Hell Swift-da async/await va Kotlin-da Flow bilan korutinlar orqali hal qilinadi.
  • Delegate bir nechta metodli protokollar uchun callback-dan afzal; callback — bir martalik operatsiyalar uchun.
  • Oddiy asinxron operatsiyalar uchun callback, ketma-ket zanjirlar uchun async/await, ko'p hodisalar uchun delegate dan foydalaning.

Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz

IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.

Loyihani muhokama qilish

Shuningdek o'qing