Android Activity Fragment share ViewModel

Goal

Use View Binding and Data Binding by Android Studio 3.6 above

Use Shared ViewModel between Activity and child Fragment

Preparation (build.gradle)

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.1"

    defaultConfig {
        applicationId "com.daiji110.viewbinding"
        minSdkVersion 21
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

    dataBinding {
        enabled = true
    }

    viewBinding {
        enabled = true
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    kotlinOptions {
        jvmTarget = "1.8"
    }

}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.core:core-ktx:1.2.0'
    implementation "androidx.fragment:fragment-ktx:1.2.4"

    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}

comipleOptions, and kotlinOptions are for Java 8 definition

androidx.fragment:fragment-ktx is to write ViewModel management easily

dataBinding and viewBinding is On

Sample

Prepare button on Activity and everytime, press button switch Fragment Vibisility

activity_main.xml

This is Activity layout codes

<?xml version="1.0" encoding="utf-8"?>
<layout 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">

    <data>
        <variable
        name="viewModel"
        type="com.daiji110.viewbinding.viewmodel.GlobalViewModel" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World!" />

        <Button
            android:id="@+id/button"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Click me"/>

        <fragment
            android:id="@+id/childman"
            android:name="com.daiji110.viewbinding.fragment.ChildFragment"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
        />
    </LinearLayout>
</layout>

Add ViewModel as data and Child fragment is under this layout

fragment_childfragment.xml

This is Fragment Layout xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <import type="android.view.View"/>
        <variable
            name="parentViewModel"
            type="com.daiji110.viewbinding.viewmodel.GlobalViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:id="@+id/parentView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:visibility="@{parentViewModel.child ? View.VISIBLE : View.GONE}"
                android:text="I am child">

            </TextView>

        </LinearLayout>

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

GlobalViewModel.kt

Shared ViewModel codes

class GlobalViewModel : ViewModel() {

    var child : ObservableBoolean = ObservableBoolean(false)

    fun switchVisible() {
        child.set(!child.get())
    }
}

MainActivity.kt

class MainActivity : AppCompatActivity() {

    private val viewModel : GlobalViewModel by viewModels<GlobalViewModel>()

    var binding : ActivityMainBinding? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding?.root)

        binding?.button?.setOnClickListener {
            viewModel.switchVisible()
        }
        binding?.lifecycleOwner = this
    }
}

Create ViewModel as LocalViewModel

Prepare binding

Add event listener

ChildFragment.kt

class ChildFragment : Fragment() {

    private var binding : FragmentChildfragmentBinding? = null

    val parentViewModel by activityViewModels<GlobalViewModel>()

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = FragmentChildfragmentBinding.inflate(inflater, container, false)
        binding?.parentViewModel = parentViewModel
        return binding?.root
    }

    override fun onDestroyView() {
        super.onDestroyView()
        binding = null
    }
}
Android
スポンサーリンク
Professional Programmer2

コメント