2 回答
TA贡献1802条经验 获得超5个赞
我在 android 中看到过很多MVVM
模式的实现。我在我的项目中遵循以下结构。我不知道这是否理想。如果错了请纠正我。
首先让我回答你的问题,
在哪里验证 MVVM 中的登录表单?
我在中进行验证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 :)"
}
}
意识形态上正确的解决方案是什么?
正如我所说,我们可以遵循许多结构在 android 中实现 MVVM。下面给出了我如何做的例子。代码中充满了注释,所以我相信它是可以自我理解的。无论如何,请随时在评论中要求任何澄清。(为了可读性,我从布局文件中删除了一些代码)
登录视图模型
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>
最后是活动
登录活动
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贡献1797条经验 获得超6个赞
首先,您应该使用双向数据绑定并将文本值分配给视图模型中的可观察字段并使用这样的函数
private fun validateFields(): Boolean {
if (email.value.isNullOrBlank()) {
return false
}
if (password.value.isNullOrBlank()) {
return false
}
return true
}
要验证您的字段,您可以根据需要添加更多级别的验证。
然后您可以将以下功能附加到布局中的登录按钮
fun loginUser() {
if (validateFields()) {
val job = viewModelScope.launch(Dispatchers.IO) {
result.postValue(
repo.makeLoginRequest(
email = email.value,
password = password.value
)
)
}
}
}
并随心所欲地使用结果,这里我使用的是实时数据和协程
检查电子邮件是否有效使用:
private fun isValidEmail(): Boolean = android.util.Patterns.EMAIL_ADDRESS.matcher(email.value).matches()
添加回答
举报