Live Data return old response then New response always in toast in User Registration using Retrofit

Live Data return old response then New response always in toast in User Registration using Retrofit

问题陈述 :当我按下注册按钮注册新用户时,它会显示来自实时数据的 toast 中的注册成功响应,但是当我尝试执行相同的按钮触发时,它会再次显示来自 API 的注册成功响应消息,然后还会显示 phone 数字存在来自 API 的响应。这也意味着实时数据的旧响应 return。那么我该如何解决这个递归实时数据响应 return 问题?

这里是问题视频link 了解问题 在这里查看 https://drive.google.com/file/d/1-hKGQh9k0EIYJcbInwjD5dB33LXV5GEn/view?usp=sharing

需要 ARGENT 帮助

我的Api界面

interface ApiServices {

    /*
    * USER LOGIN (GENERAL USER)
    * */
    @POST("authentication.php")
    suspend fun loginUser(@Body requestBody: RequestBody): Response<BaseResponse>

}

我的存储库Class

class AuthenticationRepository {

    var apiServices: ApiServices = ApiClient.client!!.create(ApiServices::class.java)
    suspend fun UserLogin(requestBody: RequestBody) = apiServices.loginUser(requestBody)
}

我的视图模型Class

class RegistrationViewModel : BaseViewModel() {

    val respository: AuthenticationRepository = AuthenticationRepository()

    private val _registerResponse = MutableLiveData<BaseResponse>()
    val registerResponse: LiveData<BaseResponse> get() = _registerResponse

    /*
    * USER REGISTRATION [GENERAL USER]
    * */
    internal fun performUserLogin(requestBody: RequestBody, onSuccess: () -> Unit) {
        ioScope.launch {
            isLoading.postValue(true)
            tryCatch({
                val response = respository.UserLogin(requestBody)
                if (response.isSuccessful) {
                    mainScope.launch {
                        onSuccess.invoke()
                        isLoading.postValue(false)
                        _registerResponse.postValue(response.body())
                    }
                } else {
                    isLoading.postValue(false)
                }

            }, {
                isLoading.postValue(false)
                hasError.postValue(it)
            })
        }
    }
}

我的注册Activity

class RegistrationActivity : BaseActivity<ActivityRegistrationBinding>() {

    override val layoutRes: Int
        get() = R.layout.activity_registration

    private val viewModel: RegistrationViewModel by viewModels()


    override fun onCreated(savedInstance: Bundle?) {
        toolbarController()


        viewModel.isLoading.observe(this, {
            if (it) showLoading(true) else showLoading(false)
        })


        viewModel.hasError.observe(this, {
            showLoading(false)
            showMessage(it.message.toString())
        })


        binding.registerbutton.setOnClickListener {
            if (binding.registerCheckbox.isChecked) {
                try {
                    val jsonObject = JSONObject()
                    jsonObject.put("type", "user_signup")
                    jsonObject.put("user_name", binding.registerName.text.toString())
                    jsonObject.put("user_phone", binding.registerPhone.text.toString())
                    jsonObject.put("user_password", binding.registerPassword.text.toString())
                    val requestBody = jsonObject.toString()
                        .toRequestBody("application/json; charset=utf-8".toMediaTypeOrNull())
                    viewModel.performUserLogin(requestBody) {
                        viewModel.registerResponse.observe(this){
                            
                           showMessage(it.message.toString())
                          //return old reponse here then also new reponse multiple time
    
                        }
                    }
                } catch (e: JSONException) {
                    e.printStackTrace()
                }
            } else {
                showMessage("Please Accept Our Terms & Conditions")
            }
        }
    }

    override fun toolbarController() {
        binding.backactiontoolbar.menutitletoolbar.text = "Registration"
        binding.backactiontoolbar.menuicontoolbar.setOnClickListener { onBackPressed() }
    }

    override fun processIntentData(data: Uri) {}

}

LiveData 是一个状态持有者,它并不是真的要用作事件流。然而,有许多关于该主题的文章,例如 this one which describe the possible solutions, including SingleLiveEvent 实施取自 google 个样本。

但截至目前,kotlin 协程库提供了更好的解决方案。特别是,channels are very useful for event streams, because they implement fan-out behaviour, so you can have multiple event consumers, but each event will be handled only once. Channel.receiveAsFlow can be very convenient to expose the stream as flow. Otherwise, SharedFlow 是事件总线实现的一个很好的候选者。请注意 replayextraBufferCapacity 参数。

您的 registerResponse 实时数据在按钮点击侦听器中观察,这就是它观察两次的原因!您的 registerResponse 实时数据应该观察按钮点击侦听器一侧的数据 -

覆盖乐趣 onCreated(savedInstance: Bundle?) { toolbarController()

    viewModel.isLoading.observe(this, {
        if (it) showLoading(true) else showLoading(false)
    })
    
    viewModel.registerResponse.observe(this){
       showMessage(it.message.toString())
    }


    viewModel.hasError.observe(this, {
        showLoading(false)
        showMessage(it.message.toString())
    })


    binding.registerbutton.setOnClickListener {
        if (binding.registerCheckbox.isChecked) {
            try {
                val jsonObject = JSONObject()
                jsonObject.put("type", "user_signup")
                jsonObject.put("user_name", binding.registerName.text.toString())
                jsonObject.put("user_phone", binding.registerPhone.text.toString())
                jsonObject.put("user_password", binding.registerPassword.text.toString())
                val requestBody = jsonObject.toString()
                    .toRequestBody("application/json; charset=utf-8".toMediaTypeOrNull())
                viewModel.performUserLogin(requestBody) {
                    
                }
            } catch (e: JSONException) {
                e.printStackTrace()
            }
        } else {
            showMessage("Please Accept Our Terms & Conditions")
        }
    }
}