AndroidX ViewModel একটি ব্রিজ হিসেবে কাজ করে, আপনার শেয়ার করা বিজনেস লজিক এবং UI কম্পোনেন্টের মধ্যে একটি স্পষ্ট চুক্তি স্থাপন করে। এই প্যাটার্ন প্ল্যাটফর্ম জুড়ে ডেটার সামঞ্জস্য নিশ্চিত করতে সাহায্য করে, পাশাপাশি প্রতিটি প্ল্যাটফর্মের স্বতন্ত্র চেহারার জন্য UI কাস্টমাইজ করার সুবিধা দেয়। আপনি Android-এ Jetpack Compose এবং iOS-এ SwiftUI-এর মাধ্যমে আপনার UI ডেভেলপ করা চালিয়ে যেতে পারেন।
ViewModel ব্যবহারের সুবিধা এবং ViewModel-এর প্রাথমিক ডকুমেন্টেশনে সব ফিচার সম্পর্কে আরও পড়ুন।
ডিপেন্ডেন্সি সেট-আপ করুন
আপনার প্রোজেক্টে KMP ViewModel সেট-আপ করতে,
libs.versions.toml ফাইলে ডিপেন্ডেন্সি নির্ধারণ করুন:
[versions]
androidx-viewmodel = 2.11.0
[libraries]
androidx-lifecycle-viewmodel = { module = "androidx.lifecycle:lifecycle-viewmodel", version.ref = "androidx-viewmodel" }
তারপর আপনার KMP মডিউলের জন্য build.gradle.kts ফাইলে আর্টিফ্যাক্ট যোগ করুন
এবং ডিপেন্ডেন্সি api হিসেবে ঘোষণা করুন, কারণ এই ডিপেন্ডেন্সি বাইনারি ফ্রেমওয়ার্কে
এক্সপোর্ট করা হবে:
// You need the "api" dependency declaration here if you want better access to the classes from Swift code.
commonMain.dependencies {
api(libs.androidx.lifecycle.viewmodel)
}
Swift থেকে অ্যাক্সেস করার জন্য ViewModel API এক্সপোর্ট করুন
ডিফল্ট হিসেবে, আপনার কোডবেসে যোগ করা যেকোনও লাইব্রেরি অটোমেটিক
বাইনারি ফ্রেমওয়ার্কে এক্সপোর্ট করা হবে না। API এক্সপোর্ট করা না হলে, সেগুলি
বাইনারি ফ্রেমওয়ার্ক থেকে তখনই উপলভ্য হয় যখন আপনি শেয়ার করা কোডে সেগুলি ব্যবহার করেন
(iosMain বা commonMain সোর্স সেট থেকে)। সেক্ষেত্রে, API-তে প্যাকেজ প্রিফিক্স থাকবে, যেমন ViewModel ক্লাস Lifecycle_viewmodelViewModel ক্লাস হিসেবে উপলভ্য হবে। ডিপেন্ডেন্সি এক্সপোর্ট করা সম্পর্কে আরও জানতে বাইনারিতে ডিপেন্ডেন্সি
এক্সপোর্ট করা দেখুন।
অভিজ্ঞতা উন্নত করতে, আপনি build.gradle.kts ফাইলের export সেট-আপ ব্যবহার করে বাইনারি ফ্রেমওয়ার্কে ViewModel ডিপেন্ডেন্সি এক্সপোর্ট করতে পারবেন, যেখানে আপনি iOS বাইনারি ফ্রেমওয়ার্ক সংজ্ঞায়িত করেন, যা Kotlin কোডের মতো Swift কোড থেকেও সরাসরি ViewModel API অ্যাক্সেসযোগ্য করে তোলে:
listOf(
iosX64(),
iosArm64(),
iosSimulatorArm64(),
).forEach {
it.binaries.framework {
// Add this line to all the targets you want to export this dependency
export(libs.androidx.lifecycle.viewmodel)
baseName = "shared"
}
}
(ঐচ্ছিক) JVM ডেস্কটপে viewModelScope ব্যবহার করা
ViewModel-এ coroutines রান করার সময়, viewModelScope প্রপার্টি Dispatchers.Main.immediate-এর সাথে
যুক্ত থাকে, যা ডিফল্ট হিসেবে ডেস্কটপে
উপলভ্য নাও থাকতে পারে। এটি যাতে সঠিকভাবে কাজ করে, তার জন্য আপনার প্রোজেক্টে kotlinx-coroutines-swing
ডিপেন্ডেন্সি যোগ করুন:
// Optional if you use JVM Desktop
desktopMain.dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-swing:[KotlinX Coroutines version]")
}
আরও তথ্যের জন্য Dispatchers.Main ডকুমেন্টেশন
দেখুন।
commonMain বা androidMain থেকে ViewModel ব্যবহার করুন
শেয়ার করা commonMain-এ ViewModel ক্লাস ব্যবহার করার জন্য কোনও নির্দিষ্ট প্রয়োজনীয়তা নেই,
androidMain sourceSet-এর ক্ষেত্রেও নেই। শুধু একটি বিষয় মনে রাখতে হবে,
আপনি কোনও প্ল্যাটফর্ম-নির্দিষ্ট API ব্যবহার করতে পারবেন না এবং আপনাকে সেগুলি অ্যাবস্ট্র্যাক্ট করতে হবে। যেমন, আপনি ViewModel কনস্ট্রাক্টর প্যারামিটার হিসেবে Android Application ব্যবহার করলে, আপনাকে এটি অ্যাবস্ট্র্যাক্ট করে এই API থেকে মাইগ্রেট করতে হবে।
প্ল্যাটফর্ম-নির্দিষ্ট কোড কীভাবে ব্যবহার করতে হয় সেই সম্পর্কে আরও তথ্য Kotlin Multiplatform-এ প্ল্যাটফর্ম-নির্দিষ্ট কোড-এ উপলভ্য।
যেমন, নিম্নলিখিত স্নিপেটে ViewModel ক্লাস ও তার ফ্যাক্টরি আছে,
যা commonMain-এ সংজ্ঞায়িত করা হয়েছে:
// commonMain/MainViewModel.kt class MainViewModel( private val repository: DataRepository, ) : ViewModel() { /* some logic */ } // ViewModelFactory that retrieves the data repository for your app. val mainViewModelFactory = viewModelFactory { initializer { MainViewModel(repository = getDataRepository()) } } fun getDataRepository(): DataRepository = DataRepository()
তারপর, আপনার UI কোডে, আপনি স্বাভাবিকভাবে ViewModel পুনরুদ্ধার করতে পারেন:
// androidApp/ui/MainScreen.kt @Composable fun MainScreen( viewModel: MainViewModel = viewModel( factory = mainViewModelFactory, ), ) { // observe the viewModel state }
SwiftUI থেকে ViewModel ব্যবহার করা
Android-এ, ViewModel লাইফসাইকেল অটোমেটিক ম্যানেজ করা হয় এবং
ComponentActivity, Fragment, NavBackStackEntry (নেভিগেশন ২) বা
rememberViewModelStoreNavEntryDecorator (নেভিগেশন ৩)-এ স্কোপ করা হয়। তবে, iOS-এ SwiftUI-এর ক্ষেত্রে
AndroidX ViewModel-এর সমতুল্য কোনও বিল্ট-ইন ফিচার নেই।
আপনার SwiftUI অ্যাপের সাথে ViewModel শেয়ার করতে, আপনাকে কিছু সেট-আপ কোড যোগ করতে হবে।
জেনেরিক্সে সাহায্য করার জন্য একটি ফাংশন তৈরি করো
Android-এ ক্লাস রেফারেন্স রিফ্লেকশন ফিচার ব্যবহার করে একটি জেনেরিক ViewModel ইনস্ট্যান্স ইনস্ট্যান্টিয়েট করা হয়। যেহেতু Objective-C জেনেরিক Kotlin বা Swift-এর সব ফিচার সাপোর্ট করে না, তাই আপনি সরাসরি Swift থেকে জেনেরিক টাইপের ViewModel উদ্ধার করতে পারবেন না।
এই সমস্যার সমাধান করতে, আপনি একটি হেল্পার ফাংশন তৈরি করতে পারেন যা জেনেরিক টাইপের পরিবর্তে
ObjCClass ব্যবহার করবে এবং তারপর ইনস্ট্যান্টিয়েট করার জন্য ViewModel ক্লাস ফিরিয়ে আনতে
getOriginalKotlinClass ব্যবহার করবে:
// iosMain/ViewModelResolver.ios.kt /** * This function allows retrieving any ViewModel from Swift Code with generics. We only get * [ObjCClass] type for the [modelClass], because the interop between Kotlin and Swift code * doesn't preserve the generic class, but we can retrieve the original KClass in Kotlin. */ @BetaInteropApi @Throws(IllegalArgumentException::class) fun ViewModelStore.resolveViewModel( modelClass: ObjCClass, factory: ViewModelProvider.Factory, key: String?, extras: CreationExtras? = null, ): ViewModel { @Suppress("UNCHECKED_CAST") val vmClass = getOriginalKotlinClass(modelClass) as? KClass<ViewModel> require(vmClass != null) { "The modelClass parameter must be a ViewModel type." } val provider = ViewModelProvider.Companion.create(this, factory, extras ?: CreationExtras.Empty) return key?.let { provider[key, vmClass] } ?: provider[vmClass] }
তারপর, আপনি Swift থেকে ফাংশন কল করতে চাইলে, T : ViewModel টাইপের জেনেরিক ফাংশন লিখতে এবং T.self ব্যবহার করতে পারবেন, যা ObjCClass-কে resolveViewModel ফাংশনে পাস করতে পারে।
SwiftUI লাইফসাইকেলে ViewModel স্কোপ কানেক্ট করুন
পরবর্তী ধাপ হল একটি IosViewModelStoreOwner তৈরি করা যা
ObservableObject এবং ViewModelStoreOwner ইন্টারফেস (প্রোটোকল) প্রয়োগ করে। SwiftUI কোডে
@StateObject হিসেবে এই ক্লাস ব্যবহার করার জন্য
ObservableObject-এর কারণ:
// iosApp/IosViewModelStoreOwner.swift class IosViewModelStoreOwner: ObservableObject, ViewModelStoreOwner { let viewModelStore = ViewModelStore() /// This function allows retrieving the androidx ViewModel from the store. /// It uses the utilify function to pass the generic type T to shared code func viewModel<T: ViewModel>( key: String? = nil, factory: ViewModelProviderFactory, extras: CreationExtras? = nil ) -> T { do { return try viewModelStore.resolveViewModel( modelClass: T.self, factory: factory, key: key, extras: extras ) as! T } catch { fatalError("Failed to create ViewModel of type \(T.self)") } } /// This is called when this class is used as a `@StateObject` deinit { viewModelStore.clear() } }
এই মালিক Android-এর মতোই একাধিক ViewModel ধরন ফিরিয়ে আনার অনুমতি দেয়।
IosViewModelStoreOwner ব্যবহার করা স্ক্রিন ডিইনিশিয়ালাইজ হয়ে deinit কল করলে,
সেইসব ViewModels-এর লাইফসাইকেল মুছে যায়। আপনি
অফিসিয়াল ডকুমেন্টেশন থেকে
ডি-ইনিশিয়ালাইজেশন সম্পর্কে আরও জানতে পারবেন।
এই পর্যায়ে, আপনি SwiftUI ভিউতে IosViewModelStoreOwner-কে @StateObject হিসেবে ইনস্ট্যান্টিয়েট করতে পারবেন এবং ViewModel ফিরিয়ে আনতে viewModel ফাংশন কল করতে পারবেন:
// iosApp/ContentView.swift struct ContentView: View { /// Use the store owner as a StateObject to allow retrieving ViewModels and scoping it to this screen. @StateObject private var viewModelStoreOwner = IosViewModelStoreOwner() var body: some View { /// Retrieves the `MainViewModel` instance using the `viewModelStoreOwner`. /// The `MainViewModel.Factory` and `creationExtras` are provided to enable dependency injection /// and proper initialization of the ViewModel with its required `AppContainer`. let mainViewModel: MainViewModel = viewModelStoreOwner.viewModel( factory: MainViewModelKt.mainViewModelFactory ) // ... // .. the rest of the SwiftUI code } }
Kotlin Multiplatform-এ উপলভ্য নয়
Android-এ উপলভ্য কিছু API, Kotlin Multiplatform-এ উপলভ্য নয়।
Hilt-এর সাথে ইন্টিগ্রেশন
Kotlin Multiplatform প্রোজেক্টের জন্য Hilt উপলভ্য নয় বলে,
আপনি সরাসরি commonMain sourceSet-এ @HiltViewModel অ্যানোটেশন সহ
ViewModels ব্যবহার করতে পারবেন না। সেক্ষেত্রে আপনাকে অন্য কোনও DI ফ্রেমওয়ার্ক ব্যবহার করতে হবে, যেমন, Koin,
kotlin-inject, Metro অথবা
Kodein। আপনি klibs.io-এ Kotlin Multiplatform-এর সাথে কাজ করে এমন সব DI ফ্রেমওয়ার্ক খুঁজে পাবেন।
SwiftUI-তে ফ্লো পর্যবেক্ষণ করা
SwiftUI-তে কো-রুটিন ফ্লো পর্যবেক্ষণ করার সুবিধা সরাসরি কাজ করে না। তবে, এই ফিচার ব্যবহার করার অনুমতি দিতে, আপনি KMP-NativeCoroutines অথবা SKIE লাইব্রেরি ব্যবহার করতে পারেন।