Skip to content

Instantly share code, notes, and snippets.

@weverb2
Last active March 19, 2023 01:30
Show Gist options
  • Save weverb2/fb4be4b9499c26759b9ec92331e019c2 to your computer and use it in GitHub Desktop.
Save weverb2/fb4be4b9499c26759b9ec92331e019c2 to your computer and use it in GitHub Desktop.
Data Binding + LIve Data Form Validation
<layout>
<data>
<variable
name="viewModel"
type="works.wever.mvvm.formvalidation.FormValidationViewModel" />
</data>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<EditText
android:id="@+id/emailAddress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/email"
android:text="@={viewModel.emailAddress}" />
<Button
android:id="@+id/saveButton"
style="@style/Widget.AppCompat.Button.Borderless.Colored"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:enabled="@{viewModel.valid}"
android:text="@string/save" />
</LinearLayout>
</layout>
import android.os.Bundle
import android.util.Log
import android.util.Patterns
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProviders
import works.wever.mvvm.R
import works.wever.mvvm.databinding.FormValidationActivityBinding
class FormValidationActivity: AppCompatActivity() {
lateinit var binding: FormValidationActivityBinding
// 1. Create the view model
val viewModel: FormValidationViewModel by lazy {
ViewModelProviders.of(this).get(FormValidationViewModel::class.java)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
title = "My Cool Form"
// 2. Inflate the layout with data binding
binding = DataBindingUtil.setContentView(this, R.layout.form_validation_activity)
binding.setLifecycleOwner(this)
// 3. Set the viewModel instance
binding.viewModel = viewModel
}
}
class FormValidationViewModel: ViewModel() {
val emailAddress = MutableLiveData<String>("")
val valid = MediatorLiveData<Boolean>().apply {
addSource(emailAddress) {
val valid = isFormValid(it)
Log.d(it, valid.toString())
value = valid
}
}
fun isFormValid(emailAddress: String): Boolean {
return Patterns.EMAIL_ADDRESS.matcher(emailAddress).matches()
}
}
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.lifecycle.Observer
import org.junit.Assert.*
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
@RunWith(RobolectricTestRunner::class)
class FormValidationViewModelTest {
@get:Rule
val instantTaskExecutorRule = InstantTaskExecutorRule()
lateinit var viewModel: FormValidationViewModel
@Before
fun setUp() {
viewModel = FormValidationViewModel()
}
@Test
fun testIsFormValid() {
val valid = viewModel.isFormValid("sundar@google.com")
assertTrue(valid)
val invalid = viewModel.isFormValid("not an email address")
assertFalse(invalid)
}
@Test
fun testValidMediator() {
viewModel.emailAddress.postValue("sundar@google.com")
val validObserver = Observer<Boolean> {
assertTrue(it)
}
viewModel.valid.observeForever(validObserver)
viewModel.valid.removeObserver(validObserver)
viewModel.emailAddress.postValue("not an email address")
val invalidObserver = Observer<Boolean> {
assertFalse(it)
}
viewModel.valid.observeForever(invalidObserver)
viewModel.valid.removeObserver(invalidObserver)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment