android - 如何将业务逻辑赋予 ViewModel Kotlin?
问题描述
作为一名学生,我正在从事一个培训项目,但我不知道如何将我的业务逻辑NewItemActivity
从NewItemViewModel
. 事实证明,我拥有在片段内验证和创建 ItemModel 的所有逻辑。这样做不好,这些都是业务逻辑中需要交给viewModel的部分。如何将业务逻辑转移到 ViewModel,但同时保持应用程序正常工作?否则我试过了,一切都为我打破了。
新项目活动.kt
class NewItemActivity : AppCompatActivity() {
private val calendar: Calendar = Calendar.getInstance()
private val viewModel: NewItemViewModel by viewModels(factoryProducer = {
NewItemViewModel.Factory()
})
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_new_item)
val saveButton = findViewById<Button>(R.id.saveButton)
val editDate = findViewById<EditText>(R.id.editDate)
val date = SimpleDateFormat("dd.MM.yyyy")
val dateDefault = date.format(calendar.timeInMillis)
editDate.setText(dateDefault)
editDate.setOnClickListener {
showDatePickerDialog()
}
saveButton.setOnClickListener {
checkStateDescriptionLayout()
if (checkStateTitleLayout()) return@setOnClickListener
if (checkStateDescriptionLayout()) return@setOnClickListener
val newItem = ItemModel(
title = editTitle.text.toString(),
description = editDescription.text.toString(),
date = Date(),
isFavorite = false
)
viewModel.saveNewItem(newItem)
Toast.makeText(this, "New item added", Toast.LENGTH_SHORT).show()
finish()
}
textChangedListener()
}
private fun showDatePickerDialog() {
val datePickerDialog = DatePickerDialog(
this@NewItemActivity,
{ _, year, monthOfYear, dayOfMonth ->
val selectedDate: String =
dayOfMonth.toString() + "." + (monthOfYear + 1) + "." + year
editDate?.setText(selectedDate)
},
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH)
)
datePickerDialog.datePicker.maxDate = calendar.timeInMillis
datePickerDialog.show()
}
private fun checkStateTitleLayout(): Boolean {
val titleLayout = findViewById<TextInputLayout>(R.id.editTitleLayout)
val checkTitleLayoutState = titleLayout.editText?.text?.toString()
val fieldIsRequired = getString(R.string.fieldIsRequired)
val error: Boolean = checkTitleLayoutState!!.isEmpty()
if (error) titleLayout.error = fieldIsRequired
return error
}
private fun checkStateDescriptionLayout(): Boolean {
val descriptionLayout = findViewById<TextInputLayout>(R.id.editDescriptionLayout)
val checkDescriptionLayoutState = descriptionLayout.editText?.text?.toString()
val fieldIsRequired = getString(R.string.fieldIsRequired)
val error: Boolean = checkDescriptionLayoutState!!.isEmpty()
if (error) descriptionLayout.error = fieldIsRequired
return error
}
private fun textChangedListener() {
val titleLayout = findViewById<TextInputLayout>(R.id.editTitleLayout)
val descriptionLayout = findViewById<TextInputLayout>(R.id.editDescriptionLayout)
titleLayout.editText?.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
override fun afterTextChanged(s: Editable?) {
titleLayout.error = null
titleLayout.isErrorEnabled = false
}
})
descriptionLayout.editText?.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
override fun afterTextChanged(s: Editable?) {
descriptionLayout.error = null
descriptionLayout.isErrorEnabled = false
}
})
}
}
新项目视图模型.kt
class NewItemViewModel(
private val repository: MyItemsRepository
) : ViewModel() {
fun saveNewItem(item: ItemModel) = repository.saveNewItem(item)
class Factory : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return NewItemViewModel(MyItemsRepositoryImpl.getInstance()) as T
}
}
}
解决方案
似乎您的主要业务逻辑包含在 onCreate 中,当您的业务逻辑很少时,这不是一个大问题,而且您的逻辑基本上是一个事件(保存 ItemModel 对象)。
如果您仍想将更多逻辑移至 ViewModel,请将 ItemModel 的创建移至 ViewModel 并提供函数以更改 ItemModel 的每个参数。它应该如下所示:
class NewItemViewModel(
private val repository: MyItemsRepository
) : ViewModel() {
private var title = ""
private var description = ""
private var date = Date()
private var isFavorite = false
fun setTitle(s: String) { title = s }
fun setDescription(s: String) { description = s }
fun setDate(d: Date) { date = d }
fun setIsFavorite(b: Boolean) { isFavorite = b }
fun saveNewItem() = repository.saveNewItem(Item(title, description, date, isFavorite))
class Factory : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return NewItemViewModel(MyItemsRepositoryImpl.getInstance()) as T
}
}
}
你可能认为这比它的价值更麻烦,你是对的。但是,为更复杂的逻辑做准备是没有害处的;)
PS我没有测试过这段代码,但应该基本正确。