Background Thread — একটি এক্সিকিউশন থ্রেড যা ইউজার ইন্টারফেসের সাথে সংযুক্ত নয়, দীর্ঘস্থায়ী অপারেশনের জন্য ডিজাইন করা হয়েছে: নেটওয়ার্ক অনুরোধ, ফাইল অপারেশন, JSON পার্সিং, ইমেজ কম্প্রেশন, এনক্রিপশন এবং ডাটাবেস কোয়েরি। iOS-এ, ব্যাকগ্রাউন্ড থ্রেডগুলি GCD (DispatchQueue.global) এবং OperationQueue-এর মাধ্যমে পরিচালিত হয়; Android-এ, Executors, WorkManager এবং Kotlin Coroutines (Dispatchers.IO, Dispatchers.Default)-এর মাধ্যমে। Apple DispatchQueue ডকুমেন্টেশন অনুযায়ী, ব্যাকগ্রাউন্ড অপারেশন শেষ হওয়ার পরে, ইন্টারফেস আপডেট করার জন্য ফলাফল Main Thread-এ ফেরত দিতে হবে।
মূল বিষয়
Background Thread — অ্যাপ্লিকেশনের যে কোনো থ্রেড যা Main Thread নয় এবং UI-তে অ্যাক্সেস নেই। এর কাজ হল প্রধান থ্রেডকে ভারী অপারেশন থেকে মুক্ত করা যাতে ইন্টারফেস প্রতিক্রিয়াশীল থাকে। অপারেটিং সিস্টেম ব্যাকগ্রাউন্ড থ্রেডগুলি CPU কোর জুড়ে বিতরণ করে, একাধিক কাজ সমান্তরালে সম্পাদনের অনুমতি দেয়। iOS স্বয়ংক্রিয়ভাবে GCD-এর মাধ্যমে থ্রেড পুল পরিচালনা করে, Android Java Executors পুলের মাধ্যমে।
Main Thread-এর বিপরীতে, যা ইভেন্টগুলি ক্রমিকভাবে (একের পর এক) প্রক্রিয়া করে, ব্যাকগ্রাউন্ড থ্রেডগুলি সমান্তরালে চলতে পারে, শুধুমাত্র CPU কোরের সংখ্যা দ্বারা সীমিত। উদাহরণস্বরূপ, 8-কোর ডিভাইসে উল্লেখযোগ্য ধীরগতি ছাড়াই 8টি সমান্তরাল ব্যাকগ্রাউন্ড কাজ চালানো যেতে পারে। তবে, অত্যধিক সংখ্যক থ্রেড (শত শত) thread starvation — কোরের জন্য প্রতিযোগিতা এবং কনটেক্সট সুইচ (context switch) ওভারহেড বৃদ্ধির দিকে নিয়ে যায়।
Quality of Service (QoS) — iOS প্রক্রিয়া যা ব্যাকগ্রাউন্ড কাজের অগ্রাধিকার নির্দিষ্ট করার অনুমতি দেয়। মান: .userInteractive (সর্বোচ্চ, প্রায় Main Thread), .userInitiated (ব্যবহারকারী ফলাফলের জন্য অপেক্ষা করছে), .default (মানক), .utility (ব্যবহারকারী সরাসরি অপেক্ষা করছে না), .background (সর্বনিম্ন, সিঙ্ক এবং ইনডেক্সিংয়ের জন্য)। Android-এ, সমতুল্য হল Thread.setPriority() 1 থেকে 10 পর্যন্ত, তবে Android থ্রেড অগ্রাধিকারের গ্রুপ পরিচালনার জন্য cgroups-ও ব্যবহার করে।
DispatchQueue.global(qos:) — iOS-এ ব্যাকগ্রাউন্ড কিউ পাওয়ার প্রাথমিক উপায়। GCD (Grand Central Dispatch) স্বয়ংক্রিয়ভাবে একটি থ্রেড পুল তৈরি করে এবং কোর জুড়ে কাজ বিতরণ করে। DispatchQueue.global(qos: .background).async {} কল সর্বনিম্ন অগ্রাধিকার সহ ব্যাকগ্রাউন্ড কিউতে একটি ব্লক পাঠায়। যে কাজের ফলাফল অবিলম্বে প্রয়োজন, তাদের জন্য .userInitiated বা .utility ব্যবহার করুন।
OperationQueue — GCD-এর উপরে একটি উচ্চ-স্তরের অ্যাবস্ট্রাকশন যা অপারেশনের মধ্যে নির্ভরতা, সর্বোচ্চ সমবর্তী অপারেশন সংখ্যা (maxConcurrentOperationCount) এবং অগ্রাধিকার নির্ধারণের অনুমতি দেয়। OperationQueue জটিল মাল্টিটাস্কিং চেইনের জন্য সুবিধাজনক: ফাইল ডাউনলোড → আনজিপ → ক্যাশে সংরক্ষণ। ডিফল্টরূপে, OperationQueue ব্যাকগ্রাউন্ড থ্রেড ব্যবহার করে যদি না অন্যথায় নির্দিষ্ট করা হয়।
import UIKit
class ImageDownloader {
func downloadImagesSequentially() {
let urls = ["https://example.com/1.png", "https://example.com/2.png"]
// maxConcurrentOperationCount = 2 সহ OperationQueue
let queue = OperationQueue()
queue.maxConcurrentOperationCount = 2
queue.qualityOfService = .utility
for urlString in urls {
queue.addOperation {
guard let url = URL(string: urlString),
let data = try? Data(contentsOf: url)
else { return }
DispatchQueue.main.async {
print("লোড হয়েছে: \(url.lastPathComponent)")
}
}
}
}
// GCD: বিভিন্ন QoS সহ গ্লোবাল ব্যাকগ্রাউন্ড কিউ
func backgroundTaskWithQoS() {
DispatchQueue.global(qos: .userInitiated).async {
// উচ্চ অগ্রাধিকার — ব্যবহারকারী ফলাফলের জন্য অপেক্ষা করছে
let result = self.heavyComputation()
DispatchQueue.main.async {
self.showResult(result)
}
}
}
private func heavyComputation() -> String {
Thread.sleep(forTimeInterval: 2) // কাজের অনুকরণ
return "গণনার ফলাফল"
}
private func showResult(_ result: String) {
print("Result on Main: \(result)")
}
}
উদাহরণে, OperationQueue qualityOfService = .utility-এর মাধ্যমে ব্যাকগ্রাউন্ড QoS সহ দুটি ইমেজ সমান্তরালে লোড করে (maxConcurrentOperationCount = 2)। GCD পদ্ধতি backgroundTaskWithQoS .userInitiated সহ একটি গ্লোবাল কিউ ব্যবহার করে যার ফলাফলের জন্য ব্যবহারকারী অপেক্ষা করছে। উভয় পদ্ধতি UI আপডেট করার জন্য DispatchQueue.main-এ ফিরে এসে শেষ হয় — এটি iOS-এ একটি বাধ্যতামূলক প্রয়োজনীয়তা।
GCD দুটি ধরনের কিউ সমর্থন করে: serial (ক্রমিক) এবং concurrent (সমবর্তী)। Serial কিউ একের পর এক কাজ সম্পাদন করে — এটি লক ছাড়াই শেয়ার্ড রিসোর্স (ফাইল, DB) অ্যাক্সেস করার জন্য সুবিধাজনক। Concurrent কিউ সমান্তরালে কাজ সম্পাদন করে, সেগুলি উপলব্ধ কোর জুড়ে বিতরণ করে। DispatchQueue.global সবসময় concurrent হয়। Serial কিউ তৈরি করতে, DispatchQueue(label: "com.app.queue") ব্যবহার করুন।
Android ব্যাকগ্রাউন্ড থ্রেডের জন্য বিভিন্ন স্তরের অ্যাবস্ট্রাকশন প্রদান করে। ক্লাসিক পদ্ধতি হল java.util.concurrent.Executors.newFixedThreadPool(n) বা Executors.newCachedThreadPool()। আধুনিক পদ্ধতি হল Kotlin Coroutines যার সাথে Dispatchers.IO (I/O-র জন্য: নেটওয়ার্ক, ফাইল, DB) এবং Dispatchers.Default (CPU-নিবিড় কাজের জন্য: সর্টিং, ইমেজ প্রসেসিং)। WorkManager বিলম্বিত এবং গ্যারান্টিযুক্ত ব্যাকগ্রাউন্ড কাজের জন্য।
HandlerThread — নিজস্ব Looper (বার্তা কিউ) সহ ব্যাকগ্রাউন্ড থ্রেড তৈরির জন্য একটি বিশেষ Android ক্লাস। Executors-এর বিপরীতে, HandlerThread Handler-এর মাধ্যমে বার্তা এবং Runnable পাঠানোর অনুমতি দেয়। এটি এমন অপারেশনের জন্য ব্যবহৃত হয় যেগুলির কিউইং প্রয়োজন (যেমন, ক্রমিক DB লেখা)। ব্যবহারের পরে, রিসোর্স মুক্ত করতে quit() বা quitSafely() কল করতে হবে।
// Android: Executors এবং Coroutines Dispatchers
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.util.concurrent.Executors
class DataRepository {
private val ioExecutor = Executors.newFixedThreadPool(4)
// Executors-এর মাধ্যমে ক্লাসিক পদ্ধতি
fun loadDataLegacy(callback: (String) -> Unit) {
ioExecutor.execute {
val result = readFromFile()
val handler = android.os.Handler(android.os.Looper.getMainLooper())
handler.post { callback(result) }
}
}
// Coroutines-এর মাধ্যমে আধুনিক পদ্ধতি
suspend fun loadDataCoroutines(): String {
return withContext(Dispatchers.IO) {
// ফাইল অপারেশন — ব্যাকগ্রাউন্ড পুলে সম্পাদিত হচ্ছে
readFromFile()
}
// ফলাফল স্বয়ংক্রিয়ভাবে Dispatchers.Main-এ ফেরত আসে
}
// Dispatchers.Default-এ CPU-নিবিড় কাজ
suspend fun processImage(pixels: IntArray): IntArray {
return withContext(Dispatchers.Default) {
// সর্টিং, ফিল্টারিং — Default পুলে সম্পাদিত হচ্ছে
pixels.sortedArray()
}
}
private fun readFromFile(): String {
Thread.sleep(1000) // ফাইল থেকে পড়ার অনুকরণ
return "file_content"
}
fun cleanup() {
ioExecutor.shutdown()
}
}
DataRepository উদাহরণ Android-এ ব্যাকগ্রাউন্ড থ্রেডের বিবর্তন দেখায়। লিগ্যাসি পদ্ধতি loadDataLegacy Main Thread-এ ফেরত আসার জন্য Handler-সহ Executors.newFixedThreadPool(4) ব্যবহার করে। আধুনিক loadDataCoroutines withContext(Dispatchers.IO) ব্যবহার করে — coroutine থ্রেড ব্লক না করেই এক্সিকিউশনের সময় স্থগিত হয় এবং স্বয়ংক্রিয়ভাবে Main Thread-এ পুনরায় শুরু হয়। Dispatchers.Default CPU-বাউন্ড অপারেশনের জন্য সুপারিশ করা হয় (সর্টিং, ফিল্টারিং, ডেটা ট্রান্সফর্মেশন)।
Kotlin Coroutines — থ্রেড নিয়ে কাজ করার একটি উপায় মাত্র নয়, বরং একটি মৌলিকভাবে ভিন্ন মডেল: অ্যাসিঙ্ক্রোনাস কাজগুলি নির্দিষ্ট থ্রেডের সাথে আবদ্ধ নয় এবং ব্লক না করেই স্থগিত হতে পারে। এর মানে হল যে ব্যাকগ্রাউন্ডে থাকাকালীন, coroutine থ্রেড দখল করে না বরং এটি অন্যান্য কাজের জন্য মুক্ত করে। স্থগিতকরণ প্রক্রিয়া 4–8 থ্রেডের পুলে thread starvation ছাড়াই শত শত হাজার সমবর্তী কাজ চালানোর অনুমতি দেয়।
তিনটি প্রধান ডিসপ্যাচার: Dispatchers.Main (UI, একটি থ্রেড), Dispatchers.IO (ডিফল্টরূপে 64 থ্রেড ব্লকিং অপারেশনের জন্য: নেটওয়ার্ক, ফাইল, DB), Dispatchers.Default (CPU কোরের সংখ্যার সমান, নিবিড় গণনার জন্য)। withContext-এর মাধ্যমে এগুলি একত্রিত করে, ডেভেলপার কলব্যাক তৈরি না করেই থ্রেডের মধ্যে সুইচ করে। withContext একটি suspend ফাংশন যা কাজ শেষ না হওয়া পর্যন্ত নিয়ন্ত্রণ ফেরত দেয় না।
// Coroutines: ব্যাকগ্রাউন্ড কাজের কম্পোজিশন
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
suspend fun loadUserProfile(userId: String): UserProfile =
coroutineScope {
// বিভিন্ন উৎস থেকে সমান্তরাল ডেটা লোডিং
val user = async(Dispatchers.IO) { fetchUser(userId) }
val posts = async(Dispatchers.IO) { fetchPosts(userId) }
val avatar = async(Dispatchers.Default) {
processAvatar(fetchAvatar(userId))
}
// await() — সব কাজ শেষ না হওয়া পর্যন্ত স্থগিত থাকে
UserProfile(
user = user.await(),
posts = posts.await(),
avatar = avatar.await()
)
}
data class UserProfile(
val user: String,
val posts: List<String>,
val avatar: ByteArray
)
suspend fun fetchUser(id: String): String { delay(300); return "User:$id" }
suspend fun fetchPosts(id: String): List<String> { delay(500); return listOf("Post1") }
suspend fun fetchAvatar(id: String): ByteArray { delay(200); return ByteArray(1024) }
suspend fun processAvatar(data: ByteArray): ByteArray { delay(100); return data }
loadUserProfile ফাংশন async-এর মাধ্যমে তিনটি সমান্তরাল ব্যাকগ্রাউন্ড কাজ শুরু করে। fetchUser এবং fetchPosts IO-বাউন্ড (নেটওয়ার্ক), Dispatchers.IO-তে সম্পাদিত হয়। processAvatar CPU-বাউন্ড (ইমেজ প্রসেসিং), Dispatchers.Default-এ সম্পাদিত হয়। await() সব কাজ শেষ না হওয়া পর্যন্ত coroutine স্থগিত করে। মোট এক্সিকিউশন সময় তিনটি কাজের মধ্যে সর্বোচ্চ সময়ের (fetchPosts-এর জন্য 500 ms) সমান, তাদের যোগফলের নয়। এটি ক্রমিক এক্সিকিউশনের তুলনায় coroutines-এর একটি মূল সুবিধা।
Structured concurrency — একটি নীতি যেখানে প্রতিটি coroutine-এর একটি প্যারেন্ট স্কোপ থাকে এবং প্যারেন্ট বাতিল করলে চাইল্ড coroutines স্বয়ংক্রিয়ভাবে বাতিল হয়। Android-এ, lifecycleScope Activity ধ্বংস হলে সব coroutine বাতিল করে। viewModelScope ViewModel পরিষ্কার হলে তা করে। এটি ব্যাকগ্রাউন্ড কাজের লিক প্রতিরোধ করে: ব্যবহারকারী স্ক্রিন বন্ধ করলে, ব্যাকগ্রাউন্ডে থাকাকালীন coroutine আর প্রয়োজন নেই এমন ডেটা লোড করা চালিয়ে যাবে না।
WorkManager — একটি Android Jetpack লাইব্রেরি যা ব্যাকগ্রাউন্ড কাজ সম্পাদনের জন্য যা ডিভাইস রিস্টার্ট বা অ্যাপ বন্ধ হওয়ার পরেও সম্পূর্ণ করতে হবে। Executors এবং coroutines-এর বিপরীতে, যা অ্যাপ প্রক্রিয়ার মধ্যে থাকে, WorkManager কাজটি সিস্টেম ডিসপ্যাচারের কাছে হস্তান্তর করে যা উপযুক্ত শর্তে (নেটওয়ার্ক উপলব্ধতা, ব্যাটারি চার্জ, খালি স্থান) সম্পাদনের গ্যারান্টি দেয়। WorkManager ডেটা সিঙ্ক্রোনাইজেশন, লগ আপলোড এবং ব্যাকআপের জন্য উপযুক্ত।
WorkManager-এ একটি কাজ হল একটি ক্লাস যা Worker (বা coroutines-এর জন্য CoroutineWorker) এক্সটেন্ড করে। Worker.doWork() WorkManager-এর দেওয়া ব্যাকগ্রাউন্ড থ্রেডে সম্পাদিত হয়। ফলাফল Result.success(), Result.retry() বা Result.failure()-এর মাধ্যমে ফেরত দেওয়া হয়। কাজগুলি চেইন করা যেতে পারে: oneTimeWorkRequest.andThen(nextRequest).enqueue()। WorkManager সীমাবদ্ধতা (Constraints) বিবেচনা করে নিজেই সর্বোত্তম এক্সিকিউশন সময় বেছে নেয়।
// Coroutines-সহ WorkManager
import android.content.Context
import androidx.work.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
class SyncWorker(
appContext: Context,
workerParams: WorkerParameters
) : CoroutineWorker(appContext, workerParams) {
override suspend fun doWork(): Result {
// Dispatchers.Default-এ সম্পাদিত হচ্ছে (ডিফল্টরূপে)
return withContext(Dispatchers.IO) {
try {
syncDataToServer()
Result.success()
} catch (e: Exception) {
if (runAttemptCount < 3) Result.retry() else Result.failure()
}
}
}
private suspend fun syncDataToServer() {
// সিঙ্ক্রোনাইজেশনের অনুকরণ
delay(1000)
}
}
// সীমাবদ্ধতা সহ WorkManager কাজ শুরু করা
fun scheduleSync(context: Context) {
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresBatteryNotLow(true)
.build()
val syncWork = OneTimeWorkRequestBuilder<SyncWorker>()
.setConstraints(constraints)
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 10, java.util.concurrent.TimeUnit.SECONDS)
.build()
WorkManager.getInstance(context).enqueue(syncWork)
}
SyncWorker CoroutineWorker — Worker-এর একটি সংস্করণ যা coroutines সমর্থন করে, এক্সটেন্ড করে। doWork() Dispatchers.Default-এ সম্পাদিত হয়, withContext-এর মাধ্যমে নেটওয়ার্ক অপারেশনের জন্য IO-তে সুইচ করে। Constraints নিশ্চিত করে যে সিঙ্ক্রোনাইজেশন শুধুমাত্র নেটওয়ার্ক উপলব্ধ এবং ব্যাটারি চার্জ নিম্ন স্তরের নিচে না হলে শুরু হয়। EXPONENTIAL সহ BackoffCriteria পুনরায় চেষ্টার মধ্যে ব্যবধান বাড়ায়: 10, 20, 40 সেকেন্ড।
নিয়মিত কাজের জন্য (প্রতি 15 মিনিটে সিঙ্ক্রোনাইজেশন, প্রতি ঘন্টায় অ্যানালিটিক্স পাঠানো), WorkManager PeriodicWorkRequestBuilder প্রদান করে। সর্বনিম্ন ব্যবধান 15 মিনিট। OneTimeWorkRequest-এর বিপরীতে, PeriodicWorkRequest সঠিক ব্যবধান পালনের গ্যারান্টি দেয় না — সিস্টেম ব্যাটারি বাঁচাতে একাধিক পর্যায়ক্রমিক কাজকে গ্রুপ করতে পারে। সঠিক ব্যবধানের জন্য, AlarmManager ব্যবহার করুন, তবে Android 12+ এ সঠিক অ্যালার্মের উপর বিধিনিষেধ মনে রাখবেন।
প্রথম ভুল — প্রতিটি কাজের জন্য নতুন Thread তৈরি করা। new Thread().start() স্ট্যাকের জন্য ~1 MB বরাদ্দ করে একটি নেটিভ থ্রেড তৈরি করে। 100টি সমান্তরাল কাজের জন্য, এটি স্ট্যাকের জন্য 100 MB, প্লাস কনটেক্সট সুইচ ওভারহেড। থ্রেড পুল ব্যবহার করুন: Executors.newFixedThreadPool(n) (Android) বা DispatchQueue.global() (iOS) — তারা থ্রেড পুনরায় ব্যবহার করে, ওভারহেড বহুগুণ হ্রাস করে।
দ্বিতীয় ভুল — সিঙ্ক্রোনাইজেশন ছাড়া একাধিক ব্যাকগ্রাউন্ড থ্রেড থেকে মিউটেবল অবস্থা অ্যাক্সেস করা। যদি দুটি ব্যাকগ্রাউন্ড থ্রেড একই ArrayList বা HashMap-এ একসাথে লিখে, তবে রেস কন্ডিশন দেখা দেয়: Android-এ ConcurrentModificationException, iOS-এ ডেটা দূষণ। সমাধান: থ্রেড-সুরক্ষিত কালেকশন (ConcurrentHashMap, CopyOnWriteArrayList) ব্যবহার করুন বা একটি একক কিউ (DispatchQueue serial) এর মাধ্যমে অ্যাক্সেস সিরিয়ালাইজ করুন।
তৃতীয় ভুল — লাইফসাইকেল ম্যানেজমেন্ট ছাড়া ব্যাকগ্রাউন্ড কাজ। Activity বা ViewModel-এর লাইফসাইকেলের সাথে বাঁধা ছাড়া গ্লোবাল স্কোপে coroutine শুরু করা লিকের দিকে নিয়ে যায়: স্ক্রিন ধ্বংস হওয়ার পরেও কাজ চলতে থাকে। Android-এ, lifecycleScope (Activity/Fragment) বা viewModelScope (ViewModel) ব্যবহার করুন। iOS-এ, ক্লোজারে weak self ব্যবহার করুন এবং deinit-এ কাজ বাতিল করুন।
সচরাচর জিজ্ঞাসিত প্রশ্ন
Background Thread — একটি থ্রেড যাতে UI-র সাথে সম্পর্কিত নয় এমন অপারেশন সম্পাদিত হয়: নেটওয়ার্ক অনুরোধ, ফাইল পড়া/লেখা, JSON পার্সিং, গণনা। এটি Main Thread-কে ভারী কাজ থেকে মুক্ত করে, ইন্টারফেসের প্রতিক্রিয়াশীলতা বজায় রাখে। iOS-এ, ব্যাকগ্রাউন্ড থ্রেড GCD (DispatchQueue.global) এর মাধ্যমে পরিচালিত হয়; Android-এ, Executors বা Kotlin Coroutines (Dispatchers.IO, Dispatchers.Default) এর মাধ্যমে।
Dispatchers.IO ব্লকিং I/O অপারেশনের জন্য ডিজাইন করা হয়েছে: ফাইল পড়া, নেটওয়ার্ক অনুরোধ, DB-র সাথে কাজ করা। এর পুল 64টি থ্রেডের। Dispatchers.Default CPU-নিবিড় কাজের জন্য: সর্টিং, ফিল্টারিং, ইমেজ প্রসেসিং। এর পুল CPU কোরের সংখ্যার সমান। I/O অপারেশনের জন্য Dispatchers.Default ব্যবহার করলে সব কোর ব্লক হতে পারে, এবং CPU কাজের জন্য Dispatchers.IO ব্যবহার করলে অত্যধিক সংখ্যক থ্রেড তৈরি হতে পারে।
DispatchQueue.global(qos: .background).async { } গ্লোবাল ব্যাকগ্রাউন্ড কিউতে একটি ব্লক পাঠায়। ব্যাকগ্রাউন্ড কাজ শেষ হওয়ার পরে, UI আপডেট করার জন্য DispatchQueue.main.async { }-এর মাধ্যমে মূল থ্রেডে ফিরে আসতে হবে। ক্রমিক ব্যাকগ্রাউন্ড কাজের জন্য, maxConcurrentOperationCount = 1 সহ OperationQueue বা DispatchQueue(label: "serial") ব্যবহার করুন।
সুপারিশকৃত ব্যাকগ্রাউন্ড থ্রেডের সংখ্যা CPU কোরের সংখ্যা এবং IO-বাউন্ড কাজের জন্য 1 যোগের সমান। আধুনিক 8-কোর ডিভাইসে, এটি 9টি থ্রেড। শত শত থ্রেড তৈরি করলে thread starvation হয়: OS কাজ সম্পাদনের চেয়ে কনটেক্সট সুইচিং-এ বেশি সময় ব্যয় করে। iOS-এ GCD এবং Android-এ Executors বর্তমান ডিভাইসের জন্য স্বয়ংক্রিয়ভাবে থ্রেড পুল অপ্টিমাইজ করে।
Kotlin Coroutines-এ, Main Thread-এ ফিরে আসা স্বয়ংক্রিয়ভাবে ঘটে যদি coroutine Main স্কোপে (lifecycleScope.launch, viewModelScope.launch) শুরু করা হয়। withContext(Dispatchers.IO) ফাংশন coroutine-কে IO থ্রেডে স্থগিত করে, এবং শেষ হওয়ার পরে স্বয়ংক্রিয়ভাবে যে ডিসপ্যাচার থেকে শুরু করা হয়েছিল (সাধারণত Main) সেখানে পুনরায় শুরু করে। DispatchQueue.main.async-এর স্পষ্ট কলের প্রয়োজন নেই।
সারাংশ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন