2 回答

TA貢獻(xiàn)1802條經(jīng)驗(yàn) 獲得超5個(gè)贊
我在 android 中看到過(guò)很多MVVM
模式的實(shí)現(xiàn)。我在我的項(xiàng)目中遵循以下結(jié)構(gòu)。我不知道這是否理想。如果錯(cuò)了請(qǐng)糾正我。
首先讓我回答你的問(wèn)題,
在哪里驗(yàn)證 MVVM 中的登錄表單?
我在中進(jìn)行驗(yàn)證ViewModel
class LogInViewModel : ViewModel() {
? ? ...
? ? fun performValidation() {
? ? ? ? if (username.isBlank()) {
? ? ? ? ? ? logInResult.value = "Invalid username"
? ? ? ? ? ? return
? ? ? ? }
? ? ? ? if (password.isBlank()) {
? ? ? ? ? ? logInResult.value = "Invalid password"
? ? ? ? ? ? return
? ? ? ? }
? ? ? ? logInResult.value = "Valid credentials :)"
? ? }
}
意識(shí)形態(tài)上正確的解決方案是什么?
正如我所說(shuō),我們可以遵循許多結(jié)構(gòu)在 android 中實(shí)現(xiàn) MVVM。下面給出了我如何做的例子。代碼中充滿(mǎn)了注釋?zhuān)晕蚁嘈潘强梢宰晕依斫獾摹o(wú)論如何,請(qǐng)隨時(shí)在評(píng)論中要求任何澄清。(為了可讀性,我從布局文件中刪除了一些代碼)
登錄視圖模型
class LogInViewModel : ViewModel() {
? ? /**
? ? ?* Two way bind-able fields
? ? ?*/
? ? var username: String = ""
? ? var password: String = ""
? ? /**
? ? ?* To pass login result to activity
? ? ?*/
? ? private val logInResult = MutableLiveData<String>()
? ? fun getLogInResult(): LiveData<String> = logInResult
? ? /**
? ? ?* Called from activity on login button click
? ? ?*/
? ? fun performValidation() {
? ? ? ? if (username.isBlank()) {
? ? ? ? ? ? logInResult.value = "Invalid username"
? ? ? ? ? ? return
? ? ? ? }
? ? ? ? if (password.isBlank()) {
? ? ? ? ? ? logInResult.value = "Invalid password"
? ? ? ? ? ? return
? ? ? ? }
? ? ? ? logInResult.value = "Valid credentials :)"
? ? }
}
登錄處理器
/**
?* To pass UI events to activity
?*/
interface LogInHandler {
? ? /**
? ? ?* Will be called when login button gets clicked
? ? ?*/
? ? fun onLogInClicked()
}
activity_login.xml
<layout>
? ? <data>
? ? ? ? <variable
? ? ? ? ? ? name="viewModel"
? ? ? ? ? ? type="com.theapache64.mvvmloginsample.LogInViewModel" />
? ? ? ? <variable
? ? ? ? ? ? name="handler"
? ? ? ? ? ? type="com.theapache64.mvvmloginsample.LogInHandler" />
? ? </data>
? ? <androidx.constraintlayout.widget.ConstraintLayout>
? ? ? ? <EditText
? ? ? ? ? ? ...
? ? ? ? ? ? android:text="@={viewModel.username}" <!--Two way binding username-->
? ? ? ? />
? ? ? ? <EditText
? ? ? ? ? ? ...
? ? ? ? ? ? android:text="@={viewModel.password}" <!--Two way binding password-->
? ? ? ? />
? ? ? ? <Button
? ? ? ? ? ? ...
? ? ? ? ? ? android:onClick="@{()->handler.onLogInClicked()}" <!--Invoked on button click-->
? ? ? ? />
? ? </androidx.constraintlayout.widget.ConstraintLayout>
</layout>
最后是活動(dòng)
登錄活動(dòng)
class LogInActivity : AppCompatActivity(), LogInHandler {
? ? private lateinit var viewModel: LogInViewModel
? ? override fun onCreate(savedInstanceState: Bundle?) {
? ? ? ? super.onCreate(savedInstanceState)
? ? ? ? // Binding
? ? ? ? val binding =
? ? ? ? ? ? DataBindingUtil.setContentView<ActivityLoginBinding>(this, R.layout.activity_login)
? ? ? ? // ViewModel
? ? ? ? this.viewModel = ViewModelProviders.of(this).get(LogInViewModel::class.java)
? ? ? ? // Setting binding params
? ? ? ? binding.viewModel = viewModel
? ? ? ? binding.handler = this
? ? ? ? // Watching for login result
? ? ? ? viewModel.getLogInResult().observe(this, Observer { result ->
? ? ? ? ? ? Toast.makeText(this, result, Toast.LENGTH_SHORT).show()
? ? ? ? })
? ? }
? ? override fun onLogInClicked() {
? ? ? ? viewModel.performValidation()
? ? }
}
我在 GitHub 中托管了完整的源代碼。

TA貢獻(xiàn)1797條經(jīng)驗(yàn) 獲得超6個(gè)贊
首先,您應(yīng)該使用雙向數(shù)據(jù)綁定并將文本值分配給視圖模型中的可觀察字段并使用這樣的函數(shù)
private fun validateFields(): Boolean {
if (email.value.isNullOrBlank()) {
return false
}
if (password.value.isNullOrBlank()) {
return false
}
return true
}
要驗(yàn)證您的字段,您可以根據(jù)需要添加更多級(jí)別的驗(yàn)證。
然后您可以將以下功能附加到布局中的登錄按鈕
fun loginUser() {
if (validateFields()) {
val job = viewModelScope.launch(Dispatchers.IO) {
result.postValue(
repo.makeLoginRequest(
email = email.value,
password = password.value
)
)
}
}
}
并隨心所欲地使用結(jié)果,這里我使用的是實(shí)時(shí)數(shù)據(jù)和協(xié)程
檢查電子郵件是否有效使用:
private fun isValidEmail(): Boolean = android.util.Patterns.EMAIL_ADDRESS.matcher(email.value).matches()
添加回答
舉報(bào)