2

我在 kotlin 流程中相对较新,我正在使用 android 中的流程创建登录模块。过去几天,我在 ViewModels 中收集它时一直被困在流程中,但是当我使用错误的凭据请求其缓存所有状态时,我遇到了问题。输入正确的凭据后,用户导航到主 Activity,但 MainActivity 的实例正在使用每个发出的状态创建:Example(User Enter 3 wrong Credential and 1 Right Credential: 4 Instance of MainActivity Created)。那么,有什么方法可以取消之前的发射并只显示最新的请求。我也在使用 collectLatest ,但它也不起作用。下面是代码。

登录活动

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(mViewBinding.root)

        loginListener()
        

    

    }
    override fun onStart() {
        super.onStart()
        initViews()
        handleNetworkChanges()
    }

    private fun observeLogin() {
        lifecycleScope.launchWhenCreated {
          mViewModel.loginCredentials.collect { state ->
              when(state){
                  is State.Loading -> {
                      showLoading()
                  }
                  is State.Success -> {
                      Timber.d("I m in Success" + state.data)
                      val intent = Intent(this@LoginActivity,MainActivity::class.java)
                      startActivity(intent)
                      closeLoading()
                      finish()

                  }
                  is State.Error -> {
                      val errorResponse = gson.fromJson(state.message,LoginResponse::class.java)
                      showToast(errorResponse.messages)
                      closeLoading()
                  }
              }
          }
        }
    }
private fun loginListener() {
        mViewBinding.neumorphButtonSignIn.setOnClickListener {
            observeLogin()
            phoneNumber = mViewBinding.edtPhoneNumber.text.toString()
            pin = mViewBinding.oldPIN.text.toString()

            if (phoneNumber.isValidPhone()) {
                sendLoginCredentials(phoneNumber ,pin)
            }
        else {


                mViewBinding.edtPhoneNumber.snack("Please Enter valid phone number") {
                    action("ok") {
                        dismiss()
                    }
                }


            }
        }
    }
    private fun sendLoginCredentials(phoneNumber: String , pin: String) = mViewModel.postLoginCredentials("03XXXX" , "1234")

登录视图模型

@ExperimentalCoroutinesApi
@HiltViewModel
class LoginViewModel @Inject constructor(
    private val loginRepository: LoginRepository,

) : ViewModel() {
    private val _loginCredentials: MutableStateFlow<State<LoginResponse>> = MutableStateFlow(State.Empty())
    val loginCredentials: StateFlow<State<LoginResponse>> get() = _loginCredentials

    fun postLoginCredentials(phoneNumber: String, pin: String) {
        Timber.d("postLoginCredentials: $phoneNumber + $pin")
        _loginCredentials.value = State.loading()
        viewModelScope.launch {
            loginRepository.login(LoginRequest(phoneNumber,pin))
                .map { response -> State.fromResource(response) }
                .collect{state -> _loginCredentials.value = state }
        }
    }

}

登录存储库

class LoginRepository @Inject constructor(
    private val apiInterface: APIInterface
) {

    fun login(loginRequest: LoginRequest): Flow<ResponseAPI<LoginResponse>> {
        return object : NetworkBoundRepository<LoginRequest, LoginResponse>() {

            override suspend fun fetchFromRemote(): Response<LoginResponse> = apiInterface.createLoginRequest(
               loginRequest
           )
        }.asFlow()
    }

网络绑定存储库

abstract class NetworkBoundRepository<RESULT, REQUEST> {

    fun asFlow() = flow<ResponseAPI<REQUEST>> {

        val apiResponse = fetchFromRemote()

        val remotePosts = apiResponse.body()

        if (apiResponse.isSuccessful && remotePosts != null) {
            emit(ResponseAPI.Success(remotePosts))
        } else {
            // Something went wrong! Emit Error state.
            emit(ResponseAPI.Failed(apiResponse.errorBody()!!.string()))
        }

        
    }.catch { e ->
        e.printStackTrace()
        emit(ResponseAPI.Failed("Network error! Can't get latest posts."))
    }


    @MainThread
    protected abstract suspend fun fetchFromRemote(): Response<REQUEST>
}

有什么方法可以创建 MainAcitivity 的一个实例而忽略较旧的发出响应?任何可以工作的操作员。非常感谢这方面的任何帮助。谢谢。

4

1 回答 1

0

实际上,observeLogin()当我将其移至onCreate(). 一切都按预期进行。因此,为不会陷入困境的新手发布此内容。

于 2021-12-16T05:39:54.547 回答