我是 kotlin 的新手,我正在嘗試在我的簡單專案中應用 mvvm 設計模式來理解。我有一個模型,視圖,視圖模型。視圖包有 mainactivity 和 2 個片段。mainactivity中有tablayout和viewpager視圖,我試圖從viewmodel中的stopwatchviewmodel訪問它們,但我無法訪問它們。stopwatchviewmodel 是一個類,但我可以從片段和主要活動中訪問。我該如何解決這個問題?
MainActivity.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".view.MainActivity">
<com.google.android.material.tabs.TabLayout
android:id="@ id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="kronometre" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="zamanlay?c?" />
</com.google.android.material.tabs.TabLayout>
<androidx.viewpager.widget.ViewPager
android:id="@ id/viewPager" <!-- the data ? want to reach-->
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/tabLayout">
</androidx.viewpager.widget.ViewPager>
StopWatchViewModel.kt
class StopWatchViewModel(val context: Context):ViewModel() {
private fun setUpTabs()
{
val fragmentManager = (context as FragmentActivity).supportFragmentManager
val adapter = ViewPageModelAdapter(fragmentManager)
adapter.addFragment(StopWatchFragment(),"stopWatchFragment")
adapter.addFragment(TimerFragment(),"timerFragment")
viewpager.adapter = adapter // <--- ? cannot access viewpager
}
}
構建.gradle
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-android-extensions' // <--- I also added kotlin extensions.
}
android {
compileSdk 31
defaultConfig {
applicationId "com.enestigli.kronometre"
minSdk 21
targetSdk 31
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures{
dataBinding = true
viewBinding = true
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1"
}
uj5u.com熱心網友回復:
設定 Views 和 Fragments 是“View”層的一部分,因此它不應該首先在 de ViewModel 中。讓這段代碼存在于實際包含這些視圖的 Fragment 或 Activity 類中。
話雖如此,一般來說,如果您的 ViewModel 需要任何東西,您可以在建構式中、在使用它們的方法中或通過一些依賴注入框架傳遞這些依賴項。
在這種情況下,您可以將 Context 和 ViewPager 物件傳遞給 setUpTabs 函式:
fun setUpTabs(context: Context, viewPager: ViewPager) {
...
}
然后從具有正確值的片段中呼叫它。
現在,由于設定視圖不是 ViewModels 職責的一部分,您可以將其重構為一些設定,其中 ViewModel 決定應該添加哪些片段,但視圖實際上處理實作。
ViewModel 決定顯示什么,但不需要任何 Views 依賴項:
class SomeViewModel() : ViewModel() {
fun getTabsToShow(): Map<String, Fragment> {
return mapOf(
"stopWatchFragment" to StopWatchFragment(),
"timerFragment" to TimerFragment())
}
}
Fragment,例如它也可以是一個 Activity,然后使用這些資訊來構建正確的視圖:
class SomeFragment : Fragment() {
override fun onViewCreated(view: View) {
val tabs = viewModel.getTabsToShow()
val fragmentManager = requireActivity().supportFragmentManager
val adapter = ViewPageModelAdapter(fragmentManager)
for ((tag, fragment) in tabs) {
adapter.addFragment(fragment, tag)
}
viewpager.adapter = adapter
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/455649.html
上一篇:如何通過Item物件的屬性過濾Flow<List<Item>并回傳一個新的Flow<List<Item>>
下一篇:遞回映射問題
