Search code examples
androidkotlinmvvmdata-binding

Android Kotlin Calling ViewModel function from View with Parameters


I am building an Android app.

I have a layout that contains a button 'saveButton'. When the user clicks the button, the onClick should call a function in my ViewModel, onSave(). This function requires 2 parameters: the text contents of 2 EditText views that are also present in the same layout.

Basically, the user has edited the name and/or the synopsis and now wants to have the ViewModel update the object's data in the database.

(Part of) my UI (.xml fragment layout):

<?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"
    tools:context=".ui.CreateEditRelationFragment">

<data>
    <variable
        name="createEditRelationViewModel"
        type="be.pjvandamme.farfiled.viewmodels.CreateEditRelationViewModel" />
</data>

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

    <Button
        android:id="@+id/saveButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/saveText"
        android:onClick="@{() -> createEditRelationViewModel.onSave(relationNameEditText.getEditText().getText().toString(), relationSynopsisEditText.getEditText().getText().toString())}" />

    <Button
        android:id="@+id/cancelButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="32dp"
        android:text="@string/cancelText"
        android:onClick="@{() -> createEditRelationViewModel.onCancel()}" />

    <EditText
        android:id="@+id/relationSynopsisEditText"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:ems="10"
        android:gravity="start|top"
        android:inputType="textMultiLine" />

    <EditText
        android:id="@+id/relationNameEditText"
        android:layout_width="@dimen/relationNameEditWidth"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:layout_marginBottom="16dp"
        android:ems="10"
        android:inputType="textPersonName"
        android:text="Name" />
</androidx.constraintlayout.widget.ConstraintLayout>

(Part of) the ViewModel:

class CreateEditRelationViewModel (
    private val relationKey: Long?,
    val database: RelationDao,
    application: Application
): AndroidViewModel(application){
private var viewModelJob = Job()

private val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)
private var relation = MutableLiveData<Relation?>()

private var _navigateToRelationDetail = MutableLiveData<Boolean>()
val navigateToRelationDetail: LiveData<Boolean>
    get() = _navigateToRelationDetail

fun onSave(name: String, synopsis: String){
    Timber.i("Got name: " + name + " and synopsis: " + synopsis)
    if(relationKey == null){
        uiScope.launch{
            relation.value = Relation(0, name, synopsis, false)
            insert(relation.value!!)
        }
    }
    else{
        uiScope.launch{
            relation.value?.name = name
            relation.value?.synopsis = synopsis
            update(relation.value)
        }
    }
    _navigateToRelationDetail.value = true
}

private suspend fun insert(newRelation: Relation){
    withContext(Dispatchers.IO){
        database.insert(newRelation)
    }
}

private suspend fun update(relation: Relation?){
    if(relation != null) {
        withContext(Dispatchers.IO) {
            database.update(relation)
        }
    }
}
}

I would want this thing to compile so that the onSave() function is called and the contents of the EditTexts passed as parameters.

I cannot manage to pass the text contents of these EditTexts. The compiler throws this error:

[databinding] {"msg":"cannot find method getEditText() in class android.widget.EditText","file":"D:\\ etc.

It does the same thing when I try to access using the .text property directly. Does anyone know what I'm doing wrong? I'm tearing my hair out.


Solution

  • getEditText() method doesn't exist and you can remove it.

    instead of;

    relationNameEditText.getEditText().getText().toString()
    

    you can do

    relationNameEditText.getText().toString()` 
    

    i.e. https://github.com/dgngulcan/droid-feed/blob/e0d0d5f4af07c5375d42b74e42c55b793319a937/app/src/main/res/layout/fragment_newsletter.xml#L120