在ViewPager的片段之一中未触发LiveData

时间:2019-11-12 07:36:26

标签: android android-livedata android-viewmodel

因此,我有一个ViewPager,它有2个片段,LogInFragmentSignUpFragment。它们都共享使用AuthViewModel的相同ViewModel AuthRepository。从AuthRepository中的Firebase接收到结果后,就将其传递到AuthViewModel中,并且将数据设置为在两个片段中都可以观察到的LiveData。但是,即使更改是从SignUpFragment开始的,实时数据总是在LogInFragment中触发,而在LogInFragment中却从未观察到。我读了一些书,有人提到也许两个片段都应该使用单独的viewmodel,实际上它们仍然是相同的AuthViewModel,但是应该由Key提供,所以这就是我所做的ViewModelProviders.of(this, viewModelFactory).get(currentKey, getViewModel()),但是仍然,没有运气。我尝试过将SignUpFragment隐藏起来,并且仅将LogInFragment留在viewpager中,并且可以使用,但是仍然不能解决问题。

AuthRepository

@Singleton
class AuthRepository @Inject constructor() {

@Inject
lateinit var firebaseAuth: FirebaseAuth
@Inject
lateinit var firebaseDatabase: FirebaseDatabase
private var listener: FirebaseDataListener<Any>? = null
private var firebaseAuthResult: Any? = null

fun setFirebaseListener(listener: FirebaseDataListener<Any>) {
    this.listener = listener
}

fun removeFirebaseListener() {
    this.listener = null
}

fun register(email: String, password: String, name: String, lastName: String, city: String): Single<Task<AuthResult>?> {
    return Single.create {
        firebaseAuth.createUserWithEmailAndPassword(email, password)
                .addOnCompleteListener { authTask ->
                    if (authTask.isSuccessful) {
                        firebaseAuthResult = authTask.result
                        listener?.onDataFetched(authTask, FirebaseResultType.SIGN_UP_COMPLETE_RESULT)
                        val userId = firebaseAuth.currentUser?.uid
                        userId?.let {
                            val user = User(userId, email, name, lastName, city)
                            firebaseDatabase.getReference(Constants.FIREBASE_USERS).push().setValue(user).addOnCompleteListener(updateUserCompleteListener)
                        }
                        if (!it.isDisposed) {
                            it.onSuccess(authTask)
                        }
                    } else {
                        handleUnsuccessfulAuth(authTask, it)
                    }
                }
    }
}

fun signIn(email: String, password: String): Single<Task<AuthResult>?> {
    return Single.create {
        firebaseAuth.signInWithEmailAndPassword(email, password)
                .addOnCompleteListener { authTask ->
                    if (authTask.isSuccessful) {
                        firebaseAuthResult = authTask.result
                        listener?.onDataFetched(authTask, FirebaseResultType.SIGN_IN_COMPLETE_RESULT)
                        if (!it.isDisposed) {
                            it.onSuccess(authTask)
                        }
                    } else {
                        handleUnsuccessfulAuth(authTask, it)
                    }
                }
    }
}

private fun handleUnsuccessfulAuth(authTask: Task<AuthResult>, it: SingleEmitter<Task<AuthResult>?>) {
    firebaseAuthResult = authTask.exception
    firebaseAuthResult?.let {
        listener?.onDataFetched(firebaseAuthResult!!, FirebaseResultType.ERROR_RESULT)
    }
    it.onError(Throwable(authTask.exception?.localizedMessage, authTask.exception))
}

private val updateUserCompleteListener = OnCompleteListener<Void> {
    if (it.isSuccessful) {
        Timber.i("#updateUserCompleteListener successful update user $it")
    } else {
        Timber.e("#updateUserCompleteListener unsuccessful update user ${it.exception}")
    }
}

}

AuthViewModel

class AuthViewModel @Inject constructor(
    private val authRepository: AuthRepository,
    private val scheduler: SchedulerProviderManager
) : ViewModel(), FirebaseDataListener<Any> {

var isLoading = ObservableField(false)
var firebaseResult = MutableLiveData<FirebaseResult>()
private val compositeDisposable by lazy { CompositeDisposable() }

override fun onDataFetched(data: Any, firebaseResultType: FirebaseResultType) {
    val firebaseResultObject = FirebaseResult(data, firebaseResultType)
    firebaseResult.value = firebaseResultObject
}

fun setAuthRepositoryListener() {
    authRepository.setFirebaseListener(this)
}

fun register(email: String, password: String, name: String, lastName: String, city: String) {
    isLoading.set(true)
    compositeDisposable.addAll(authRepository.register(email, password, name, lastName, city)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe({
                Timber.i("#register onSuccess $it")
                isLoading.set(false)
            }, {
                Timber.e("#register onError ${it.cause}")
                isLoading.set(false)
            }))
}

fun signIn(email: String, password: String) {
    isLoading.set(true)
    compositeDisposable.addAll(authRepository.signIn(email, password)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(
                    {
                        Timber.i("#signIn onSuccess $it")
                        isLoading.set(false)
                    },
                    {
                        Timber.e("#signIn onError ${it.cause}")
                        isLoading.set(false)
                    }
            ))
}

fun getFirebaseResult(): LiveData<FirebaseResult> = firebaseResult

override fun onCleared() {
    authRepository.removeFirebaseListener()
    super.onCleared()
}

}

LogInFragment

class LogInFragment : BaseFragment<AuthViewModel, FragmentLogInBinding>(true, LogInFragment::class.java.name) {

companion object {
    val ACTION_LOG_IN = LogInFragment::javaClass.name + ".action_log_in"
    val ACTION_SIGN_UP = LogInFragment::javaClass.name + ".action_sign_up"

    fun newInstance(): LogInFragment {
        val fragment = LogInFragment()
        val args = Bundle()
        fragment.arguments = args
        return fragment
    }
}

override fun getLayoutRes(): Int {
    return R.layout.fragment_log_in
}

override fun getViewModel(): Class<AuthViewModel> {
    return AuthViewModel::class.java
}

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    binder = DataBindingUtil.inflate(inflater, getLayoutRes(), container, false)
    init()
    setListeners()
    return binder.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    signInUser()
}

override fun getFirebaseAnalyticsName(): String {
    return getString(R.string.screen_log_in)
}

fun init() {
    binder.viewModel = viewModel
    binder.executePendingBindings()
    binder.progressbar.indeterminateDrawable.setColorFilter(Color.WHITE, PorterDuff.Mode.MULTIPLY)
    viewModel.setAuthRepositoryListener()
}

private fun setListeners() {
    binder.tvRegisterNow.setOnClickListener { UtilsManager.sendActionToActivity(fragmentInteractionCallback, ACTION_SIGN_UP) }
    binder.logInHolder.setOnClickListener {
        if (resolveInputFields()) {
            viewModel.signIn(binder.etEmail.text.toString(), binder.etPassword.text.toString())
        }
    }
}

private fun signInUser() {
    viewModel.getFirebaseResult().observe(this, Observer<FirebaseResult> { result ->
        when (result.firebaseResult) {
            FirebaseResultType.SIGN_IN_COMPLETE_RESULT -> UtilsManager.sendActionToActivity(fragmentInteractionCallback, ACTION_LOG_IN)
            FirebaseResultType.ERROR_RESULT -> {
                if (result.data is Exception) {
                    when {
                        result.data is FirebaseAuthInvalidUserException -> longToast(R.string.wrong_email_pass).show()
                    }
                }
            }
            else -> Timber.i("signInUser ${result.firebaseResult}")
        }
    })
}

}

0 个答案:

没有答案