AndroidX ViewModel একটি সেতু হিসেবে কাজ করে, যা আপনার শেয়ার্ড বিজনেস লজিক এবং আপনার UI উপাদানগুলির মধ্যে একটি স্পষ্ট চুক্তি স্থাপন করে। এই প্যাটার্নটি প্ল্যাটফর্ম জুড়ে ডেটার ধারাবাহিকতা নিশ্চিত করতে সাহায্য করে, একই সাথে প্রতিটি প্ল্যাটফর্মের স্বতন্ত্র চেহারার জন্য UI গুলিকে কাস্টমাইজ করতে সক্ষম করে। আপনি Android-এ Jetpack Compose এবং iOS-এ SwiftUI ব্যবহার করে আপনার UI তৈরি করা চালিয়ে যেতে পারেন।
ViewModel ব্যবহারের সুবিধা এবং ViewModel এর প্রাথমিক ডকুমেন্টেশনে সমস্ত বৈশিষ্ট্য সম্পর্কে আরও পড়ুন।
নির্ভরতা সেট আপ করুন
আপনার প্রোজেক্টে KMP ViewModel সেট আপ করতে, libs.versions.toml ফাইলে নির্ভরতা নির্ধারণ করুন:
[versions]
androidx-viewmodel = 2.10.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)
}
সুইফট থেকে অ্যাক্সেসের জন্য ViewModel API গুলি রপ্তানি করুন
ডিফল্টরূপে, আপনার কোডবেসে যোগ করা যেকোনো লাইব্রেরি স্বয়ংক্রিয়ভাবে বাইনারি ফ্রেমওয়ার্কে রপ্তানি হবে না। যদি API গুলি রপ্তানি না করা হয়, তবে আপনি যদি শেয়ার্ড কোডে ( iosMain বা commonMain সোর্স সেট থেকে) সেগুলি ব্যবহার করেন তবেই বাইনারি ফ্রেমওয়ার্ক থেকে সেগুলি পাওয়া যাবে। সেই ক্ষেত্রে, API গুলিতে প্যাকেজ প্রিফিক্স থাকবে, উদাহরণস্বরূপ একটি ViewModel ক্লাস Lifecycle_viewmodelViewModel ক্লাস হিসাবে উপলব্ধ থাকবে। নির্ভরতা রপ্তানি সম্পর্কে আরও তথ্যের জন্য বাইনারিগুলিতে রপ্তানি নির্ভরতা পরীক্ষা করুন।
অভিজ্ঞতা উন্নত করার জন্য, আপনি build.gradle.kts ফাইলে থাকা export সেটআপ ব্যবহার করে ViewModel নির্ভরতা বাইনারি ফ্রেমওয়ার্কে রপ্তানি করতে পারেন যেখানে আপনি iOS বাইনারি ফ্রেমওয়ার্ক সংজ্ঞায়িত করেন, যা ViewModel API গুলিকে Swift কোড থেকে সরাসরি অ্যাক্সেসযোগ্য করে তোলে যেমন Kotlin কোড থেকে:
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 ব্যবহার করুন
ViewModel ক্লাসটি shared commonMain তে, অথবা androidMain sourceSet থেকে ব্যবহারের জন্য কোনও নির্দিষ্ট প্রয়োজনীয়তা নেই। একমাত্র বিবেচনার বিষয় হল আপনি কোনও প্ল্যাটফর্ম-নির্দিষ্ট API ব্যবহার করতে পারবেন না এবং আপনাকে সেগুলি বিমূর্ত করতে হবে। উদাহরণস্বরূপ, যদি আপনি একটি Android Application ViewModel কনস্ট্রাক্টর প্যারামিটার হিসাবে ব্যবহার করেন, তাহলে আপনাকে এটি বিমূর্ত করে এই API থেকে দূরে স্থানান্তর করতে হবে।
প্ল্যাটফর্ম-নির্দিষ্ট কোড কীভাবে ব্যবহার করবেন সে সম্পর্কে আরও তথ্য কোটলিন মাল্টিপ্ল্যাটফর্মের প্ল্যাটফর্ম-নির্দিষ্ট কোডে পাওয়া যাবে।
উদাহরণস্বরূপ, নিম্নলিখিত স্নিপেটে একটি 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 ব্যবহার করুন
অ্যান্ড্রয়েডে, ViewModel জীবনচক্র স্বয়ংক্রিয়ভাবে পরিচালিত হয় এবং ComponentActivity , Fragment , NavBackStackEntry (Navigation 2), অথবা rememberViewModelStoreNavEntryDecorator (Navigation 3) এর সাথে সংযুক্ত হয়। তবে iOS-এ SwiftUI-তে AndroidX ViewModel-এর জন্য কোনও বিল্ট-ইন সমতুল্য নেই।
আপনার SwiftUI অ্যাপের সাথে ViewModel শেয়ার করতে, আপনাকে কিছু সেটআপ কোড যোগ করতে হবে।
জেনেরিকের সাথে সাহায্য করার জন্য একটি ফাংশন তৈরি করুন
একটি জেনেরিক ViewModel ইনস্ট্যান্স ইন্সট্যান্টিয়েট করার জন্য Android-এ একটি ক্লাস রেফারেন্স রিফ্লেকশন ফিচার ব্যবহার করা হয়। যেহেতু Objective-C জেনেরিক কোটলিন বা সুইফটের সকল ফিচার সাপোর্ট করে না , তাই আপনি সরাসরি Swift থেকে জেনেরিক টাইপের ViewModel পুনরুদ্ধার করতে পারবেন না।
এই সমস্যা সমাধানের জন্য, আপনি একটি সহায়ক ফাংশন তৈরি করতে পারেন যা জেনেরিক টাইপের পরিবর্তে ObjCClass ব্যবহার করবে এবং তারপর getOriginalKotlinClass ব্যবহার করে ViewModel ক্লাসটি পুনরুদ্ধার করবে যাতে তা ইনস্ট্যান্টিয়েট করা যায়:
// 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 ফাংশনে পাস করতে পারে।
ViewModel স্কোপকে SwiftUI লাইফসাইকেলের সাথে সংযুক্ত করুন
পরবর্তী ধাপ হল একটি IosViewModelStoreOwner তৈরি করা যা ObservableObject এবং ViewModelStoreOwner ইন্টারফেস (প্রোটোকল) বাস্তবায়ন করে। ObservableObject এর কারণ হল SwiftUI কোডে @StateObject হিসেবে এই ক্লাসটি ব্যবহার করতে সক্ষম হওয়া:
// 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() } }
এই মালিক অ্যান্ড্রয়েডের মতোই একাধিক ViewModel প্রকার পুনরুদ্ধার করার অনুমতি দেয়। IosViewModelStoreOwner ব্যবহার করে স্ক্রিনটি deinit কল করলে ViewModels এর জীবনচক্র সাফ হয়ে যায়। আপনি অফিসিয়াল ডকুমেন্টেশনে deinitialization সম্পর্কে আরও জানতে পারেন।
এই মুহুর্তে, আপনি একটি 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 } }
কোটলিন মাল্টিপ্ল্যাটফর্মে উপলব্ধ নয়
অ্যান্ড্রয়েডে উপলব্ধ কিছু API কোটলিন মাল্টিপ্ল্যাটফর্মে উপলব্ধ নয়।
হিল্টের সাথে ইন্টিগ্রেশন
যেহেতু হিল্ট কোটলিন মাল্টিপ্ল্যাটফর্ম প্রকল্পের জন্য উপলব্ধ নয়, তাই আপনি commonMain sourceSet-এ @HiltViewModel অ্যানোটেশন সহ সরাসরি ViewModels ব্যবহার করতে পারবেন না। সেক্ষেত্রে আপনাকে কিছু বিকল্প DI ফ্রেমওয়ার্ক ব্যবহার করতে হবে, উদাহরণস্বরূপ, Koin , kotlin-inject , Metro , অথবা Kodein । আপনি klibs.io- তে Kotlin মাল্টিপ্ল্যাটফর্মের সাথে কাজ করে এমন সমস্ত DI ফ্রেমওয়ার্ক খুঁজে পেতে পারেন।
SwiftUI-তে প্রবাহ পর্যবেক্ষণ করুন
SwiftUI-তে কোরোটিন ফ্লো পর্যবেক্ষণ সরাসরি সমর্থিত নয়। তবে, আপনি এই বৈশিষ্ট্যটি সক্ষম করার জন্য KMP-NativeCoroutines অথবা SKIE লাইব্রেরি ব্যবহার করতে পারেন।