【发布时间】:2021-07-20 11:34:43
【问题描述】:
我作为一名学生正在从事一个培训项目,但我不知道如何将我的业务逻辑从NewItemActivity 转移到NewItemViewModel。事实证明,我拥有在片段内验证和创建 ItemModel 的所有逻辑。这样做不好,这些都是业务逻辑中需要交给viewModel的部分。如何将业务逻辑转移到 ViewModel,但同时保持应用程序正常工作?否则我试过了,一切都毁了我。
NewItemActivity.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
}
})
}
}
NewItemViewModel.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
}
}
}
【问题讨论】:
-
基本答案是,您的每个点击侦听器应该只在视图模型中调用一个函数。如果您遇到特定问题,我建议缩小您的问题范围,否则我认为您将无法获得任何有用的答案。
-
@Tenfour04 我了解需要将验证和显示的逻辑分开?
-
您可以使用任何您喜欢的设计策略。您不需要以任何特定方式进行操作。也许你可以更具体地了解你到底坚持了什么。
标签: android kotlin fragment android-viewmodel