Вот моя проблема, я использую mvvm для загрузки данных профиля из Dao, который был ранее обновлен, когда пользователь входит в систему. Или, если новый пользователь загружает пустую модель. см. мой BasicProfileFragment и ViewModel.
Я использую LiveData для первоначального обновления фрагмента из Dao. Далее я хочу редактировать / обновлять поля разными способами. ввод с клавиатуры и обновление данных путем перехода к другим фрагментам. Где данные загружаются в виде списка с сервера. Например, щелкнув полосу Пол и перейдите к фрагменту Пол, там будут заполнены Данные. и выберите из списка там и перейдите к BasicProfileFragment. Проблема здесь в том, что когда я возвращаюсь к данным BasicProfileFragment, заполненным ранее через Dao, они исчезают с полей. Но новые данные сохраняются. Мне нужно отредактировать или исправить ранее загруженные данные и отправить обратно на сервер и обновить ответ в Dao.
My BasicProfileFragment
imports .....
class BasicProfileFragment : DaggerFragment() {
@Inject
lateinit var viewModelFactory: ViewModelProvider.Factory
private lateinit var basicProfileViewModel: BasicProfileViewModel
private var filterEventHasBeenHandled = false
companion object {
const val FILTER_EVENT_HANDLED = "filterEventHasBeenHandled"
}
override fun onSaveInstanceState(outState: Bundle) {
outState.run { putBoolean(FILTER_EVENT_HANDLED, filterEventHasBeenHandled) }
super.onSaveInstanceState(outState)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
filterEventHasBeenHandled = savedInstanceState?.getBoolean(FILTER_EVENT_HANDLED) ?: false
basicProfileViewModel = activityViewModel(viewModelFactory){
observe(userDataState) { handleUserState(it) }
observe(submitEvent, ::handleProfileEvent)
observe(profileDataState) { handleDataState(it) }
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_basic_profile, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
if (!filterEventHasBeenHandled) {
val basicProfileModel =
arguments?.getParcelable("basicProfileModel") ?: BasicProfileModel.empty()
basicProfileViewModel.setProfile(basicProfileModel)
}
initializeView()
if (basicProfileViewModel.obtainCurrentUser() == null) {
val uid = Prefs.getString("USER_OID", "0")
loadUser(uid)
filterEventHasBeenHandled = true
}
}
private fun initializeView() {
(activity as AppCompatActivity).setSupportActionBar(toolbar)
(activity as AppCompatActivity).supportActionBar?.setDisplayHomeAsUpEnabled(true)
toolbar.setPadding(0, (activity as MainActivity).getStatusBarHeight(), 0, 0)
genderStrip.setOnClickListener {
it.hideKeyboard()
navigate(R.id.action_basicProfileFragment_to_gendersFragment)
}
private fun handleProfileEvent(submitEvent: Event<BasicProfileModel>?) {
if (filterEventHasBeenHandled && submitEvent?.hasBeenHandled == true) {
submitEvent.peekContent { renderProfileFields(it) }
} else {
submitEvent?.getContentIfNotHandled {
renderProfileFields(it)
filterEventHasBeenHandled = true
}
}
}
private fun handleUserState(userDataState: DataState<BasicProfileModel>?) { .... }
private fun handleDataState(profileDataState: DataState<BasicProfileModel>?) {....}
private fun handleError(exception: Exception) {.... }
private fun applySubmit(basicProfileModel: BasicProfileModel){
basicProfileViewModel.submitProfile(basicProfileModel)
}
private fun handleUserError(exception: Exception) {....}
private fun updatedFields(basicProfileModel: BasicProfileModel){
context?.onSuccess(R.string.updation_success)
renderProfileFields(basicProfileModel)
}
private fun renderProfileFields(basicProfileModel: BasicProfileModel) {
renderGender(basicProfileModel.genderModel)
}
private fun renderGender(genderModel: GenderModel?) {
genderModel?.let {
tvGender.visible()
tvGender.text = it.gender
} ?: tvGender.gone()
}
}
My ViewModel
imports....
class BasicProfileViewModel @Inject constructor(private val basicProfileUseCase: BasicProfileUseCase,
private val getUserUseCase: GetUserUseCase) : ViewModel() {
private val _profileDataState = MutableLiveData<DataState<BasicProfileModel>>()
val profileDataState: LiveData<DataState<BasicProfileModel>>
get() = _profileDataState
private val _userDataState = MutableLiveData<DataState<BasicProfileModel>>()
val userDataState: LiveData<DataState<BasicProfileModel>>
get() = _userDataState
private var _applySubmitEvent = MutableLiveData<Event<Any>>()
val applySubmitEvent: LiveData<Event<Any>>
get() = _applySubmitEvent
private var _submitEvent = MutableLiveData<Event<BasicProfileModel>>()
val submitEvent: LiveData<Event<BasicProfileModel>>
get() = _submitEvent
private var profile = userDataState.value?.data ?: BasicProfileModel.empty()
fun setGender(genderModel: GenderModel) {
profile.genderModel = genderModel
this._submitEvent.value = Event(profile)
}
fun setProfile(basicProfileModel: BasicProfileModel) {
this.profile = basicProfileModel.copy()
this._submitEvent.value = Event(profile)
}
fun applySubmit() {
this._sharedFilter.value = Event(profile)
this._applySubmitEvent.value = Event(Any())
submitProfile(profile)
}
// for updating via NetworkDatastore
fun submitProfile(basicProfileModel: BasicProfileModel){
this.profile = basicProfileModel.copy()
launchAsync {
try {
val profileModel = asyncAwait {
BasicProfileModel(basicProfileUseCase.run(
profile.genderModel?.gender,
profile.genderModel?.genderCode))
}
_profileDataState.value = DataState.Success(profileModel)
} catch (exception: Exception) {
_profileDataState.value = DataState.Error(exception, obtainCurrentData())
}
}
}
fun obtainCurrentData() = _profileDataState.value?.data
// for updating via Dao
fun loadUser(uid: String) {
launchAsync {
try {
val profileUser = asyncAwait { BasicProfileModel(getUserUseCase.run(uid)) }
_userDataState.value = DataState.Success(profileUser)
} catch (exception: Exception) {
_userDataState.value = DataState.Error(exception, obtainCurrentUser())
}
}
}
fun obtainCurrentUser() = _userDataState.value?.data
}
Реализация класса My Event
open class Event<out T>(private val content: T) {
var hasBeenHandled = false
private set // Allow external read but not write
// Returns the content and prevents its use again.
fun getContentIfNotHandled(consumer: (T) -> Unit) {
if (!hasBeenHandled) {
hasBeenHandled = true
consumer(content)
}
}
//Returns the content, even if it's already been handled.
fun peekContent(consumer: (T) -> Unit) = consumer(content)
// Returns the content, even if it's already been handled.
fun peekContent() = content
}