Android 数据绑定不观察ViewModel中的LiveData

Android 数据绑定不观察ViewModel中的LiveData,android,mvvm,viewmodel,android-databinding,android-livedata,Android,Mvvm,Viewmodel,Android Databinding,Android Livedata,我正在尝试在ViewModel中对LiveData使用数据绑定。但在使用Transformations.map函数时,如果不显式添加观察者,则不会触发该函数。XML中的数据绑定不会为ViewModel中的LiveData生成观察者 LoginFragment.kt class LoginFragment : Fragment() { var homeViewModel: HomeViewModel? = null companion object { val

我正在尝试在ViewModel中对LiveData使用数据绑定。但在使用Transformations.map函数时,如果不显式添加观察者,则不会触发该函数。XML中的数据绑定不会为ViewModel中的LiveData生成观察者

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()
            })*/
        }
    }
}
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
    }
}
@BindingAdapter("isGone")
fun bindIsGone(view: View, isGone: Boolean) {
    view.visibility = if (isGone) {
        View.GONE
    } else {
        View.VISIBLE
    }
}
Android studio版本:

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

您的问题在“解决方案:初始化期间的连线转换”中有详细描述。建议阅读整个博客并进行更改我无法理解解决方案:在初始化过程中为我的案例连接转换。在初始化过程中移动转换,例如视图模型的构造函数。检查示例“Transformations.map函数在未显式添加观察者的情况下不会触发。”-请参见和^F
除非观察者正在查看返回的LiveData对象,否则不会计算转换-我已经告诉过您不需要
转换#*map
方法(或
MediatorLiveData
)啊。这是有道理的。
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
    }
}