Lazy Loading ڈیٹا، امیجز اور کمپوننٹس کی تاخیری لوڈنگ کی حکمت عملی ہے، جس میں وسائل کی درخواست ایپ شروع ہونے پر نہیں، بلکہ اس وقت کی جاتی ہے جب صارف کو واقعی ان کی ضرورت ہوتی ہے۔ Android Paging 3 گائیڈ کے مطابق، فہرستوں کی تاخیری لوڈنگ بڑے ڈیٹا سیٹس کے ساتھ کام کرتے وقت میموری کی کھپت کو 60–80% تک کم کرتی ہے۔ تاخیری ابتدا کلیدی اصول ہے جو تمام Lazy Loading نفاذات کی بنیاد ہے۔
اہم نکات
Lazy Loading (تاخیری لوڈنگ) ایک ڈیزائن اور اصلاح کا پیٹرن ہے جس میں ایپلیکیشن کے وسائل شروع ہونے پر نہیں، بلکہ استعمال سے فوراً پہلے لوڈ کیے جاتے ہیں۔ موبائل ڈویلپمنٹ میں، Lazy Loading تین اہم زمروں پر لاگو ہوتا ہے: ڈیٹا (فہرست صفحہ بندی)، امیجز (اسکرول کرنے پر لوڈنگ)، اور کمپوننٹس (تاخیری اسٹیک اور ویوز)۔
Lazy Loading کا الٹ Eager Loading (فوری لوڈنگ) ہے، جہاں تمام وسائل اسکرین شروع ہونے پر لوڈ کیے جاتے ہیں۔ Eager Loading پر عمل درآمد آسان ہے لیکن زیادہ میموری استعمال کرتا ہے اور پہلی نمائش کے وقت کو بڑھاتا ہے۔ ہزاروں آئٹمز والی فہرستوں کے لیے، Eager Loading محدود میموری والے آلات پر OOM (میموری ختم) کا باعث بنتا ہے۔ Lazy Loading صرف وہی لوڈ کرکے اس مسئلے کو حل کرتا ہے جو اسکرین پر دکھائی دیتا ہے اور باقی کو صارف کے اسکرول کرنے پر لوڈ کرتا ہے۔
iOS اور Android کے سیاق و سباق میں، Lazy Loading مختلف سطحوں پر لاگو کیا جاتا ہے۔ SwiftUI تاخیری رینڈرنگ کے لیے LazyVStack اور LazyHStack فراہم کرتا ہے۔ UIKit dequeueReusableCell کے ساتھ UITableView استعمال کرتا ہے۔ Android ViewHolder پول کے ساتھ RecyclerView استعمال کرتا ہے۔ ڈیٹا کی سطح پر، Paging 3 کے ساتھ Room اور NSFetchedResultsController کے ساتھ Core Data۔ مخصوص ٹیکنالوجی کا انتخاب اسٹیک اور کارکردگی کی ضروریات پر منحصر ہے۔
مرکزی اصول Lazy Loading کا یہ ہے کہ اسکرین کی موجودہ حالت کے لیے بالکل اتنی ڈیٹا لوڈ کی جائے جتنی ضرورت ہے، نیز ہموار اسکرولنگ کے لیے ایک پیش گوئی بفر۔ یہ نقطہ نظر دو میکانزم پر مبنی ہے: مرئیت سے باخبر رہنا اور عناصر کو ورچوئلائز کرنا۔
باخبر رہنے کا میکانزم تعین کرتا ہے کہ کون سے عناصر اسکرین کے دکھائی دینے والے علاقے (viewport) میں ہیں۔ Android پر، LinearLayoutManager یا GridLayoutManager findFirstVisibleItemPosition اور findLastVisibleItemPosition طریقوں کے ذریعے ایسا کرتا ہے۔ iOS میں، UIScrollView دکھائی دینے والے علاقے کا حساب لگانے کے لیے bounds.origin.y اور contentOffset.height فراہم کرتا ہے۔ جب کوئی عنصر viewport (یا پری فیچ بفر) میں داخل ہوتا ہے، تو اس کی لوڈنگ شروع ہو جاتی ہے۔ جب کوئی عنصر اسکرین چھوڑتا ہے، تو اس کے وسائل جاری کیے جا سکتے ہیں یا کیش میں منتقل کیے جا سکتے ہیں۔
// Android — RecyclerView میں مرئیت سے باخبر رہنا
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
val layoutManager = recyclerView.layoutManager as LinearLayoutManager
val lastVisible = layoutManager.findLastVisibleItemPosition()
val totalCount = layoutManager.itemCount
// بقیہ ہوں تو اگلا صفحہ لوڈ ہو رہا ہے < 5 عناصر
if (lastVisible >= totalCount - 5) {
loadMoreItems()
}
}
})
پری فیچ بفر ان عناصر کی پیش گوئی کرنے والی لوڈنگ ہے جو جلد ہی اسکرین پر ظاہر ہوں گے۔ RecyclerView layoutManager.setItemPrefetchEnabled(true) کے ذریعے GapWorker.Prefetch کو سپورٹ کرتا ہے۔ iOS UITableView UITableViewDataSourcePrefetching کے ذریعے پری فیچنگ کو سپورٹ کرتا ہے۔ پری فیچ بفر کا سائز عام طور پر 1–2 اسکرین آگے ہوتا ہے، جو اسکرول کی ہمواری اور میموری کی کھپت کے درمیان سمجھوتہ فراہم کرتا ہے۔ بہت بڑا پری فیچ بفر Lazy Loading کے فوائد کو ختم کر دیتا ہے؛ بہت چھوٹا بفر تیز اسکرولنگ کے دوران خالی جگہیں پیدا کرتا ہے۔
امیجز موبائل ایپلیکیشنز میں سب سے بھاری قسم کا وسیلہ ہیں۔ ایک 12 MP کی تصویر غیر کمپریسڈ شکل میں 3–5 MB لے سکتی ہے۔ امیجز کی Lazy Loading سینکڑوں غیر مرئی تصویروں کو میموری میں لوڈ ہونے سے روکتی ہے، جو صارف کے اوتار یا پروڈکٹ کیٹلاگ والی فہرستوں کے لیے تباہ کن ہوگا۔
Glide Android کے لیے امیج لوڈنگ کی سب سے مشہور لائبریری ہے جو کیشنگ، تبدیلیوں اور اینیمیشن کو سپورٹ کرتی ہے۔ Coil ایک ہلکا متبادل ہے، جو coroutines استعمال کرتے ہوئے Kotlin میں لکھی گئی ہے۔ دونوں لائبریریاں جب ImageView اسکرین چھوڑتا ہے تو خود بخود لوڈنگ روک دیتی ہیں اور ViewHolder کے دوبارہ استعمال پر درخواستیں منسوخ کر دیتی ہیں۔ Coil coroutines استعمال کرتی ہے اور اس کا سائز ~1.5 MB ہے جبکہ Glide ~4 MB ہے، جو اسے APK سائز پر توجہ مرکوز کرنے والے منصوبوں کے لیے ترجیحی بناتا ہے۔
// Coil — تاخیری امیج لوڈنگ
imageView.load("https://example.com/image.jpg") {
crossfade(true)
placeholder(R.drawable.placeholder)
size(512, 512)
memoryCachePolicy(CachePolicy.ENABLED)
}
Kingfisher iOS کے لیے Swift Concurrency، ڈسک اور میموری کیشنگ، اور UICollectionView کے لیے پری فیچنگ کے سپورٹ والی لائبریری ہے۔ SDWebImage ایک پرانی لائبریری ہے جس کی جڑیں Objective-C میں ہیں لیکن Swift سپورٹ کے ساتھ۔ دونوں لائبریریاں UIImageView کے ساتھ ضم ہوتی ہیں اور خود بخود لوڈنگ لائف سائیکل کا انتظام کرتی ہیں: سیل کے دوبارہ استعمال پر درخواستیں منسوخ کرتی ہیں، صرف اس وقت امیجز لوڈ کرتی ہیں جب سیل دکھائی دے رہا ہو، اور میموری کی کمی کے نوٹیفکیشن پر میموری خالی کرتی ہیں۔
بڑی ڈیٹا فہرستیں موبائل ایپس میں Lazy Loading کے بنیادی اطلاق کا شعبہ ہیں۔ نیوز فیڈ، پروڈکٹ کیٹلاگ، چیٹس، لین دین کی تاریخ — کوئی بھی اسکرین جس میں ممکنہ طور پر لامحدود فہرست ہے، صفحہ بندی اور تاخیری لوڈنگ کی ضرورت ہوتی ہے۔
Paging 3 Android Jetpack کی ایک لائبریری ہے جو مکمل تاخیری لوڈنگ سائیکل کو نافذ کرتی ہے: RemoteMediator (API + ڈیٹا بیس) سے ڈیٹا کی درخواست، Room میں کیشنگ، PagingData کے ذریعے صفحہ بہ صفحہ آؤٹ پٹ، اور AsyncPagingDataAdapter کے ذریعے ڈسپلے۔ Paging 3 تین قسم کی صفحہ بندی کو سپورٹ کرتا ہے: صفحہ پر مبنی، آئٹم پر مبنی (offset/limit)، اور کلید پر مبنی (API سے صفحہ بندی کی کلیدیں)۔ Separator لوڈنگ اشارے کے لیے صفحات کے درمیان جداکاروں کا بلٹ ان سپورٹ ہے۔
// Paging 3 — API سے تاخیری لوڈنگ
class ArticlePagingSource(
private val api: ArticleApi
) : PagingSource<Int, Article>() {
override suspend fun load(
params: LoadParams<Int>
): LoadResult<Int, Article> {
return try {
val page = params.key ?: 1
val response = api.getArticles(page)
LoadResult.Page(
data = response.items,
prevKey = page.takeIf { it > 1 }?.dec(),
nextKey = page + 1
)
} catch (e: Exception) {
LoadResult.Error(e)
}
}
}
LazyVStack SwiftUI کا ایک بلٹ ان کنٹینر ہے جو عناصر کو صرف اس وقت بناتا اور رینڈر کرتا ہے جب وہ اسکرین پر ظاہر ہوتے ہیں۔ VStack کے برعکس، جو فوری طور پر تمام بچوں کے عناصر کا لے آؤٹ شمار کرتا ہے، LazyVStack عنصر کے دکھائی دینے یا پری فیچ رینج میں داخل ہونے تک ویو کی تخلیق کو مؤخر کرتا ہے۔ LazyHStack کیروسلز کے لیے افقی ہم منصب ہے۔ بڑی فہرستوں کے لیے، Apple List استعمال کرنے کی تجویز کرتا ہے، جو اندرونی طور پر اضافی بلٹ ان ری سائیکلنگ کے ساتھ LazyVStack کی طرح کام کرتی ہے۔
// SwiftUI — تاخیری لوڈنگ کے ساتھ LazyVStack
ScrollView {
LazyVStack(spacing: 8) {
ForEach(articles) { article in
ArticleRow(article: article)
.onAppear {
if article == articles.last {
viewModel.loadMore()
}
}
}
}
}
UI کمپوننٹس کی تاخیری لوڈنگ ایک تکنیک ہے جہاں انٹرفیس کے کچھ حصے (ہیڈر، فوٹر، سیٹنگز سیکشن، ٹیبز) اسکرین شروع ہونے پر نہیں، بلکہ پہلی رسائی پر بنائے جاتے ہیں۔ یہ ابتدائی رینڈرنگ کو تیز کرتا ہے اور مرکزی تھریڈ پر بوجھ کم کرتا ہے۔
ViewStub Android میں ایک ہلکا View پلیس ہولڈر ہے جو لے آؤٹ میں جگہ نہیں لیتا اور inflate() کال ہونے تک بچوں کے View نہیں بناتا۔ شاذ و نادر ہی استعمال ہونے والے حصوں کے لیے مثالی: سرچ پینل، جدید ترتیبات، اشتہاری بلاکس۔ Fragment تاخیری لوڈنگ ایک تکنیک ہے جہاں Fragment.onCreateView اس وقت تک مؤخر کیا جاتا ہے جب تک صارف اس ٹیب پر سوئچ نہ کرے۔ یہ ViewPager میں isVisible یا UserVisibleHint کے ذریعے لاگو کیا جاتا ہے۔
AndroidX مانگ پر ماڈیولز کی تاخیری لوڈنگ کے لیے SplitInstallManager فراہم کرتا ہے۔ سیٹ اپ، تشخیص یا اضافی فیچر ماڈیول صارف کی پہلی درخواست پر ہی Dynamic Feature ماڈیول کے طور پر لوڈ کیے جاتے ہیں۔ یہ بیس ایپلیکیشن کا سائز 30–50% کم کرتا ہے اور ایک ہی وقت میں Lazy Loading کے اصول کو نہ صرف ڈیٹا کی سطح پر بلکہ کوڈ کی سطح پر بھی نافذ کرتا ہے۔
TabView SwiftUI میں ہر ٹیب کے مواد کو تاخیری طور پر لوڈ کرتا ہے — صرف اس وقت جب ٹیب فعال ہو۔ UIKit UITabBarController ڈیفالٹ طور پر شروع میں تمام بچوں کے کنٹرولرز بناتا ہے، لیکن اس رویے کو انہیں فوری طور پر tabBarController.viewControllers میں شامل نہ کرکے اور جیسے جیسے صارف سوئچ کرتا ہے انہیں تبدیل کرکے تبدیل کیا جا سکتا ہے۔ متحرک طور پر شامل کردہ arrangedSubviews کے ساتھ UIStackView بھی Lazy Loading کے اصول پر عمل کرتا ہے — صرف اس وقت Subview شامل کریں جب صارف کوئی ایسا عمل کرے جس کے لیے انٹرفیس کے اس حصے کی ضرورت ہو۔
مجموعی اسکرین لوڈنگ کو بهتر بنانے کے لیے، تمام سطحوں پر Lazy Loading کو یکجا کریں: شاذ و نادر استعمال ہونے والے حصوں کے لیے ViewStub، ڈیٹا کے لیے Paging 3، امیجز کے لیے Glide/Coil، اور Hilt/Dagger Scopes یا Swinject کے ذریعے تاخیری ViewModel ابتدا۔ یہ نقطہ نظر ایک ایسی اسکرین دیتا ہے جو 3 GB RAM والے بجٹ ڈیوائسز پر بھی 200–400 ms میں لوڈ ہوتی ہے۔
اکثر پوچھے گئے سوالات
اگر اسکرین یقینی طور پر تھوڑے آئٹمز (20 تک) دکھاتی ہے اور سب کی فوری ضرورت ہے، تو Lazy Loading ضرورت سے زیادہ ہے۔ ان فہرستوں کے لیے جو شاذ و نادر ہی اسکرول کی جاتی ہیں، Eager Loading نمایاں کارکردگی کے نقصان کے بغیر لاگو کرنا آسان اور تیز ہو سکتا ہے۔
بڑی فہرستوں کے لیے میموری کی چوٹی کھپت کو 3–10 گنا کم کرتا ہے، کیونکہ میموری میں صرف دکھائی دینے والے عناصر اور پری فیچ بفر محفوظ ہوتے ہیں۔ تاہم، پری فیچ اور امیج کیشنگ شامل کرنا معتدل میموری اوور ہیڈ پیدا کرتا ہے جسے منظم کرنے کی ضرورت ہے۔
List سوائپ، ڈریگ اینڈ ڈراپ اور بلٹ ان سلیکشن کے ساتھ یکساں ڈیٹا کے لیے ترجیحی ہے۔ LazyVStack مختلف سیل اقسام، حصوں اور غیر معیاری فاصلوں کے ساتھ کسٹم لے آؤٹ کے لیے ہے۔ List اندرونی طور پر اضافی فعالیت کے ساتھ LazyVStack کی طرح کام کرتی ہے۔
Android پر، View کا درجہ بندی دیکھنے کے لیے Layout Inspector استعمال کریں: Lazy Loading کے ساتھ، زیادہ تر عناصر درخت سے غائب ہونے چاہئیں۔ iOS پر، Xcode Debug View Hierarchy استعمال کریں۔ اگر اسکرولنگ کے دوران تمام عناصر موجود ہوں، تو Lazy Loading کام نہیں کر رہا۔
دونوں پیرامیٹرز اہم ہیں، لیکن ترجیح پلیٹ فارم پر منحصر ہے۔ iOS پر ARC اور موثر میموری مینجمنٹ کے ساتھ، ترجیح لوڈنگ کی رفتار ہے۔ Android پر JVM اور GC کے ساتھ، ترجیح میموری کی بچت ہے، کیونکہ مرکزی تھریڈ میں ہر مختص GC منجمد کا سبب بن سکتا ہے۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں