I am trying to use Data binding with LiveData in ViewModel. But when using Transformations.map functions not trigged without adding observers explicitly. Data binding in XML not generate observers for LiveData in ViewModel.
LoginFragment.kt
class LoginFragment : Fragment() {
var homeViewModel: HomeViewModel? = null
companion object {
val TAG : String = "LoginFragment"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
homeViewModel = ViewModelProviders.of(this).get(HomeViewModel::class.java)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val binding = DataBindingUtil.inflate<FragmentLoginBinding>(inflater, R.layout.fragment_login, container, false)
.apply {
setLifecycleOwner(this@LoginFragment)
loginButton.setOnClickListener {
signInWithEmail()
}
}
return binding.root
}
/*private fun observeHomeFragmentUIDataLiveData() {
homeViewModel?.homeFragmentUIDataLiveData?.observe(this, Observer {
val email = it.email
Toast.makeText(activity,email, Toast.LENGTH_SHORT).show()
})
}
private fun observeLoginErrorEventLiveData() {
homeViewModel?.loginErrorEventLiveData?.observe(this, Observer {
Toast.makeText(activity,it, Toast.LENGTH_SHORT).show()
})
}*/
/**
* Sign In via Email
*/
fun signInWithEmail(){
val email = email_text_input_layout.editText?.text.toString()
val password = password_text_input_layout.editText?.text.toString()
var cancel : Boolean? = false
var focusView : View? = null
if(password.isEmpty()){
password_text_input_layout.error = getString(R.string.this_field_is_required)
focusView = password_text_input_layout
cancel = true
}
if(email.isEmpty()){
email_text_input_layout.error = getString(R.string.this_field_is_required)
focusView = email_text_input_layout
cancel = true
}
if(cancel!!){
focusView?.requestFocus()
}
else{
homeViewModel?.signInWithEmail(email,password)
/*homeViewModel?.signInWithEmail(email,password)?.observe(this, Observer {
val email = it
Toast.makeText(activity,""+email, Toast.LENGTH_SHORT).show()
})*/
}
}
}
fragment_login.xml
<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="homeViewModel" type="com.rramprasad.adminapp.HomeViewModel"/>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="LoginFragment">
<!-- Skipped some code for clarity -->
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/error_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{homeViewModel.loginErrorEventLiveData.value}"
app:isGone="@{homeViewModel.isLoginSuccess}"
android:textColor="@android:color/holo_orange_dark"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/password_text_input_layout"
app:layout_constraintBottom_toBottomOf="@id/login_button"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
HomeViewModel.kt
class HomeViewModel(application: Application) : AndroidViewModel(application) {
val homeRepository: HomeRepository?
init {
homeRepository = HomeRepository()
}
// UI Data for HomeFragment
val homeFragmentUIDataLiveData : MutableLiveData<HomeFragmentUIData> = MutableLiveData()
// UI Data for LoginFragment
val loginErrorEventLiveData : MutableLiveData<String> = MutableLiveData()
var isLoginSuccess: LiveData<Boolean>? = null
fun signInWithEmail(email: String, password: String) : LiveData<Boolean>? {
val signInResponseMutableLiveData : MutableLiveData<Any> = homeRepository?.signInWithEmail(email, password)!!
isLoginSuccess = Transformations.map(signInResponseMutableLiveData) { signInResponse ->
when (signInResponse) {
(signInResponse is FirebaseUser) -> {
val firebaseUserEmail = (signInResponse as FirebaseUser).email
homeFragmentUIDataLiveData.value = HomeFragmentUIData(firebaseUserEmail ?: "")
return@map true
}
else -> {
loginErrorEventLiveData.value = signInResponse.toString()
return@map false
}
}
}
return isLoginSuccess
}
}
BindingAdapters.kt
@BindingAdapter("isGone")
fun bindIsGone(view: View, isGone: Boolean) {
view.visibility = if (isGone) {
View.GONE
} else {
View.VISIBLE
}
}
Android studio version:
Android Studio 3.2 RC 3 Build #AI-181.5540.7.32.4987877, built on August 31, 2018 JRE: 1.8.0_152-release-1136-b06 x86_64 JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o macOS 10.13.4
build.gradle:
android {
compileSdkVersion 28
defaultConfig {
minSdkVersion 21
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
dataBinding {
enabled = true
}
}