Comments added
This commit is contained in:
parent
a6c8882421
commit
d579601de6
|
|
@ -40,8 +40,10 @@ class ProfileActivity : LifecycleActivity() {
|
|||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
// обнуляем поле profileViewModel
|
||||
binding.profileViewModel = null
|
||||
// необходимо вручную вызвать обновление байндингов,
|
||||
// так как автоматическое обновление не работает на этапе onDestroy
|
||||
binding.executePendingBindings()
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -25,6 +25,8 @@ import android.content.Context
|
|||
class ProfileRepository(context: Context) {
|
||||
private val loginKey = "login"
|
||||
private val preferences = context.getSharedPreferences("app_preferences", Context.MODE_PRIVATE)
|
||||
// LiveData, на которую можно подписаться
|
||||
// и получать обновления логина пользователя
|
||||
private val innerLoggedInUser = LoggedInUserLiveData()
|
||||
|
||||
val loggedInUser: LiveData<String?>
|
||||
|
|
@ -32,16 +34,22 @@ class ProfileRepository(context: Context) {
|
|||
|
||||
fun login(login: String) {
|
||||
preferences.edit().putString(loginKey, login).apply()
|
||||
innerLoggedInUser.update(login)
|
||||
notifyAboutUpdate(login)
|
||||
}
|
||||
|
||||
fun logout() {
|
||||
preferences.edit().putString(loginKey, null).apply()
|
||||
innerLoggedInUser.update(null)
|
||||
notifyAboutUpdate(null)
|
||||
}
|
||||
|
||||
private fun notifyAboutUpdate(login: String?) {
|
||||
innerLoggedInUser.update(login)
|
||||
}
|
||||
|
||||
private inner class LoggedInUserLiveData : LiveData<String?>() {
|
||||
|
||||
// так лучше не делать в конструкторе, а высчитывать текщее значение асинхронно
|
||||
// при первом вызове колбека onActive
|
||||
init {
|
||||
value = preferences.getString(loginKey, null)
|
||||
}
|
||||
|
|
@ -52,6 +60,5 @@ class ProfileRepository(context: Context) {
|
|||
fun update(login: String?) {
|
||||
postValue(login)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,23 +28,34 @@ import touchin.aacplusdbtest.utils.TextField
|
|||
|
||||
class ProfileViewModel(application: Application) : AndroidViewModel(application) {
|
||||
private val profileRepository: ProfileRepository = (application as AacPlusDbTestApp).profileRepository
|
||||
// класс Transformations — это класс-хэлпер для преобразования данных
|
||||
// метод map, просто конвертирует данные из одного типа в другой - в данном случае из String? в boolean
|
||||
private val isUserLoggedInLiveData = Transformations.map(profileRepository.loggedInUser) { login -> login != null }
|
||||
|
||||
// представляет логин авторизованного пользователя или null
|
||||
val userLogin = LifecycleLiveDataField(profileRepository.loggedInUser)
|
||||
// представляет авторизован ли пользователь
|
||||
val isUserLoggedInLiveData = Transformations.map(profileRepository.loggedInUser) { login -> login != null }
|
||||
val isUserLoggedIn = LifecycleLiveDataField(isUserLoggedInLiveData)
|
||||
// представляет логин, введенный пользователем с клавиатуры
|
||||
// TextField - это ObservableField, реализующий интерфейс TextWatcher
|
||||
// это нужно, чтобы можно было байндиться к text и addTextChangedListener,
|
||||
// организовав таким образом двустронний байндинг.
|
||||
// При вводе текста в EditText изменяется ViewModel, при изменении ViewModel — изменяется в EditText.
|
||||
val inputLogin = TextField()
|
||||
|
||||
fun loginOrLogout() {
|
||||
// необходимо получить текущее состояние - авторизован пользователь или нет и решить, что делать
|
||||
isUserLoggedInLiveData.observeForever(object : Observer<Boolean> {
|
||||
override fun onChanged(loggedIn: Boolean?) {
|
||||
if (loggedIn!!) {
|
||||
profileRepository.logout()
|
||||
} else if (inputLogin.get() != null) {
|
||||
// вызываем логин только если пользователь что-то ввел в поле ввода
|
||||
profileRepository.login(inputLogin.get())
|
||||
} else {
|
||||
// по идее, тут можно отобразить ошибку "Введите логин"
|
||||
}
|
||||
// при выполнении команды приходится отписываться вручную
|
||||
isUserLoggedInLiveData.removeObserver(this)
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ class LifecycleLiveDataField<T>(val source: LiveData<T?>) : ObservableField<T>()
|
|||
override fun addOnPropertyChangedCallback(callback: Observable.OnPropertyChangedCallback) {
|
||||
super.addOnPropertyChangedCallback(callback)
|
||||
try {
|
||||
// немножко рефлексии, по-другому никак
|
||||
val callbackListenerField = callback.javaClass.getDeclaredField("mListener")
|
||||
callbackListenerField.setAccessible(true)
|
||||
val callbackListener = callbackListenerField.get(callback) as WeakReference<ViewDataBinding>
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import android.databinding.ObservableField
|
|||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
// наследуем от ObservableField
|
||||
// имплементируем Observer (интерфейс из-подписчик для LiveData) чтобы синхронизировать значения LiveData и ObservableField
|
||||
// имплементируем Observer (подписчик для LiveData) чтобы синхронизировать значения LiveData и ObservableField
|
||||
class LiveDataField<T>(val source: LiveData<T?>) : ObservableField<T>(), Observer<T?> {
|
||||
// отслеживаем количество подписчиков на этот ObservableField
|
||||
private var observersCount: AtomicInteger = AtomicInteger(0)
|
||||
|
|
|
|||
Loading…
Reference in New Issue