Как я могу получить доступ к данным просмотра из класса в kotlin

Я новичок в kotlin и пытаюсь применить шаблон проектирования mvvm в своем простом проекте, чтобы понять. У меня есть модель, представление, представление модели. пакет просмотра имеет основную активность и 2 фрагмента. В mainactivity есть представления tablayout и viewpager, я пытаюсь получить к ним доступ из модели просмотра секундомера в модели просмотра, но не могу получить к ним доступ. 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

}
}

build.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"
}
1
0
42
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Настройка представлений и фрагментов является частью слоя «Вид», поэтому на самом деле это не должно быть в де 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())
    }
}

Фрагмент, например, это также может быть действие, а затем использует эту информацию для построения правильных представлений:

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
    }
}

Другие вопросы по теме

Похожие вопросы

Соединение okhttp tls v1.2+ установлено по умолчанию?
Flutter: персонализированная панель приложений с flexibleSpace с закругленными краями не работает должным образом
Распространение приложений Firebase (плагин fastlane): не удалось сгенерировать учетные данные из токена обновления
Событие onclick не работает в карточке? XML-файл Java
ИзмерениеResource аварийно завершает работу с сообщением «NotFoundException: тип идентификатора ресурса № 0x4 недействителен»
При нажатии кнопки назад приложение вылетает через секунду
«Конфиденциальные области, которые вы отправили на проверку, не совпадают с областями, которые запрашивает ваше приложение» React Native Google Fit
SharedPreferences проверяет, существуют ли данные
Преобразование мультимедийного изображения Android в растровое изображение для Tensorflow Lite
Получение «Не удалось раздуть ColorStateList, оставив его в рамках» при использовании ShapeableImageView