Привязка MediatorLiveData напрямую из ViewModel в View - PullRequest
0 голосов
/ 01 февраля 2019

Я пытаюсь включить / отключить кнопку, когда 4 EditTexts имеют более X символов и электронная почта действительна (игнорируйте xml, все еще применяя стили):

  <Button
            android:id="@+id/fragment_login_button"
            android:fontFamily="@font/montserrat_regular"
            android:layout_marginTop="20dp"
            android:textColor="@android:color/white"
            android:background="@drawable/button_primary"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            android:enabled="@{viewModel.createAccountDetailsValid}"
            android:layout_marginRight="20dp"
            android:text="create account "
            android:onClick="@{(theView) -> handler.onCreateClick(theView, viewModel)}"
            app:layout_constraintTop_toBottomOf="@id/fragment_login_companyText"
    />

Я заработал, используя MediatorLiveData с 4 MutableLiveData , от которых зависит кнопка, но я обнаружил, что этим я иду против стандартов MVVM , но это был единственный способ, так как MediatorLiveData позволяет только addSourceесли есть хотя бы 1 наблюдатель, взгляните на код:

на моей модели просмотра:

//USER DATA
val email: MutableLiveData<String> = MutableLiveData()
val name: MutableLiveData<String> = MutableLiveData()
val surname: MutableLiveData<String> = MutableLiveData()
val company: MutableLiveData<String> = MutableLiveData()
val createAccountDetailsValid: MediatorLiveData<Boolean> = MediatorLiveData()

fun populateMediator(owner: LifecycleOwner) {
        createAccountDetailsValid.observe(owner, Observer {  })
        createAccountDetailsValid.addSource(email) {
            createAccountDetailsValid.value = isCreateAccountDetailsValid()
        }
        createAccountDetailsValid.addSource(name) {
            createAccountDetailsValid.value = isCreateAccountDetailsValid()
        }
        createAccountDetailsValid.addSource(surname) {
            createAccountDetailsValid.value = isCreateAccountDetailsValid()
        }
        createAccountDetailsValid.addSource(company) {
            createAccountDetailsValid.value = isCreateAccountDetailsValid()
        }
    }

private fun isCreateAccountDetailsValid() : Boolean {
    if(email.value == null || name.value == null || surname.value == null || company.value == null) return false
    return android.util.Patterns.EMAIL_ADDRESS.matcher(email?.value!!).matches() && name.value?.length!! >= 3 && surname.value?.length!! >= 3 && company.value?.length!! >= 3
}

на моем фрагменте:

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    binding = DataBindingUtil.inflate(inflater, R.layout.fragment_login, container,false)
    viewModel = ViewModelProviders.of(this, viewModelFactory).get(LoginViewModel::class.java)
    binding.viewModel = viewModel
    binding.handler = LoginHandler()
    binding.setLifecycleOwner(this)
    viewModel.setLifecycleOwner(this as LifecycleOwner)
    return binding.root
}

Как я уже говорилон работает, но ViewModel имеет ссылку на View (LifecycleOwner), да, я мог бы поместить пустой наблюдатель во фрагмент, и мне не нужно передавать LifecycleOwner в ViewModel, но все еще не чувствую себя хорошо, может быть, я немногоПерфекционист здесь, но я держу пари, что есть другой способ привязки непосредственно из ViewModel вместо необходимости устанавливать isEnable, наблюдая MediatorLiveData во фрагменте?

Спасибо!

1 Ответ

0 голосов
/ 01 февраля 2019

Имеет комментарий Blackbelt, я должен был сделать что-то не так и в итоге усложнить и исправить проблему, пытаясь заставить ее работать.

Он сказал, что привязка данных соблюдает, и вы можете добавить источник в инициализации viewModel, как яи все заработало:

 val createAccountResult: MutableLiveData<Resource<Void>> = MutableLiveData()
val loginResult: MutableLiveData<Resource<Void>> = MutableLiveData()

//USER DATA
val email: MutableLiveData<String> = MutableLiveData()
val name: MutableLiveData<String> = MutableLiveData()
val surname: MutableLiveData<String> = MutableLiveData()
val company: MutableLiveData<String> = MutableLiveData()

var createAccountDetailsValid: MediatorLiveData<Boolean> = MediatorLiveData()

init {
    createAccountDetailsValid.addSource(email) {
        createAccountDetailsValid.value = isCreateAccountDetailsValid()
    }
    createAccountDetailsValid.addSource(name) {
        createAccountDetailsValid.value = isCreateAccountDetailsValid()
    }
    createAccountDetailsValid.addSource(surname) {
        createAccountDetailsValid.value = isCreateAccountDetailsValid()
    }
    createAccountDetailsValid.addSource(company) {
        createAccountDetailsValid.value = isCreateAccountDetailsValid()
    }
}

Спасибо за помощь @ Blackbelt

...