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-এর হলো স্ক্রিনের বর্তমান অবস্থার জন্য ঠিক ততটুকু ডেটা লোড করা যতটুকু প্রয়োজন, plus একটি পূর্বানুমানিক বাফার মসৃণ স্ক্রোলিংয়ের জন্য। এই পদ্ধতি দুটি প্রক্রিয়ার উপর ভিত্তি করে: দৃশ্যমানতা ট্র্যাকিং এবং উপাদান ভার্চুয়ালাইজেশন।
ট্র্যাকিং প্রক্রিয়া নির্ধারণ করে কোন উপাদানগুলি স্ক্রিনের দৃশ্যমান এলাকায় (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 একটি হালকা বিকল্প, যা করুটিন ব্যবহার করে Kotlin-এ লেখা। উভয় লাইব্রেরিই ImageView স্ক্রিন ছেড়ে গেলে স্বয়ংক্রিয়ভাবে লোডিং বিরতি দেয় এবং ViewHolder পুনরায় ব্যবহারের সময় অনুরোধ বাতিল করে। Coil করুটিন ব্যবহার করে এবং Glide-এর ~4 MB-এর তুলনায় ~1.5 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-এ যোগ না করে এবং ব্যবহারকারী স্যুইচ করার সময় এগুলিকে প্রতিস্থাপন করে পরিবর্তন করা যেতে পারে। UIStackView গতিশীলভাবে যুক্ত arrangedSubviews সহও 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 অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন