AndroidX ViewModel একটি সেতু হিসাবে কাজ করে, আপনার শেয়ার করা ব্যবসার যুক্তি এবং আপনার UI উপাদানগুলির মধ্যে একটি স্পষ্ট চুক্তি স্থাপন করে৷ এই প্যাটার্নটি প্ল্যাটফর্ম জুড়ে ডেটা সামঞ্জস্য নিশ্চিত করতে সাহায্য করে, যখন প্রতিটি প্ল্যাটফর্মের স্বতন্ত্র চেহারার জন্য UIs কাস্টমাইজ করতে সক্ষম করে। আপনি Android-এ Jetpack Compose এবং iOS-এ SwiftUI-এর সাহায্যে আপনার UI ডেভেলপ করা চালিয়ে যেতে পারেন।
ViewModel ব্যবহারের সুবিধা এবং ViewModel-এর প্রাথমিক ডকুমেন্টেশনের সমস্ত বৈশিষ্ট্য সম্পর্কে আরও পড়ুন।
নির্ভরতা সেট আপ করুন
আপনার প্রকল্পে KMP ViewModel সেট আপ করতে, libs.versions.toml
ফাইলে নির্ভরতা নির্ধারণ করুন:
[versions]
androidx-viewmodel = 2.9.3
[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 APIs রপ্তানি করুন
ডিফল্টরূপে, আপনি আপনার কোডবেসে যোগ করেন এমন কোনো লাইব্রেরি স্বয়ংক্রিয়ভাবে বাইনারি কাঠামোতে রপ্তানি হবে না। যদি 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
বা androidMain
সোর্সসেট থেকে ViewModel ক্লাস ব্যবহার করার জন্য কোন নির্দিষ্ট প্রয়োজনীয়তা নেই। একমাত্র বিবেচনা হল আপনি কোনো প্ল্যাটফর্ম-নির্দিষ্ট 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 ব্যবহার করুন
অ্যান্ড্রয়েডে, ভিউমডেল লাইফসাইকেল স্বয়ংক্রিয়ভাবে পরিচালনা করা হয় এবং একটি ComponentActivity
, Fragment
, NavBackStackEntry
(নেভিগেশন 2), বা rememberViewModelStoreNavEntryDecorator
ViewModelStoreNavEntryDecorator (নেভিগেশন 3) এর মধ্যে বিস্তৃত হয়। iOS-এ SwiftUI, যদিও, AndroidX ViewModel-এর জন্য কোনো বিল্ট-ইন সমতুল্য নেই।
আপনার SwiftUI অ্যাপের সাথে 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
ইন্টারফেস (প্রটোকল) প্রয়োগ করে। 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 প্রকার পুনরুদ্ধার করার অনুমতি দেয়, একইভাবে Android এ। যখন IosViewModelStoreOwner
ব্যবহার করে স্ক্রীনটি ডিনিটিয়ালাইজ হয়ে যায় এবং deinit
কল করে তখন সেই ভিউমডেলের জীবনচক্রটি সাফ হয়ে যায়। আপনি অফিসিয়াল ডকুমেন্টেশনে ডিইনিশিয়ালাইজেশন সম্পর্কে আরও জানতে পারেন।
এই মুহুর্তে, আপনি IosViewModelStoreOwner
কে একটি SwiftUI ভিউতে @StateObject
হিসাবে ইনস্ট্যান্টিয়েট করতে পারেন এবং একটি ভিউমডেল পুনরুদ্ধার করতে 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 } }
কোটলিন মাল্টিপ্ল্যাটফর্মে উপলব্ধ নয়
অ্যান্ড্রয়েডে উপলব্ধ কিছু এপিআই কোটলিন মাল্টিপ্ল্যাটফর্মে উপলব্ধ নয়।
হিল্টের সাথে ইন্টিগ্রেশন
যেহেতু হিল্ট কোটলিন মাল্টিপ্ল্যাটফর্ম প্রকল্পের জন্য উপলব্ধ নয়, আপনি commonMain
সোর্সসেটে @HiltViewModel
টীকা সহ সরাসরি ViewModels ব্যবহার করতে পারবেন না। সেক্ষেত্রে আপনাকে কিছু বিকল্প DI ফ্রেমওয়ার্ক ব্যবহার করতে হবে, উদাহরণস্বরূপ, Koin , kotlin-inject , Metro , বা Kodein । আপনি klibs.io এ Kotlin মাল্টিপ্ল্যাটফর্মের সাথে কাজ করে এমন সমস্ত DI ফ্রেমওয়ার্ক খুঁজে পেতে পারেন।
SwiftUI এ প্রবাহ পর্যবেক্ষণ করুন
SwiftUI-তে coroutines Flows পর্যবেক্ষণ করা সরাসরি সমর্থিত নয়। যাইহোক, আপনি হয় KMP-NativeCoroutines বা SKIE লাইব্রেরি ব্যবহার করতে পারেন এই বৈশিষ্ট্যটিকে অনুমতি দিতে।