实时数据返回旧响应,然后新响应始终在使用 Retrofit 的用户注册中吐司

问题描述

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

这里是问题视频链接以了解问题 在这里查看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 AuthenticationRepository {

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

我的视图模型类

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)
            })
        }
    }
}

我的注册活动

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)描述了可能的解决方案,包括从 Google 示例中获取的 SingleLiveEvent 实现。

但截至目前,kotlin 协程库提供了更好的解决方案。特别是,channels 对于事件流非常有用,因为它们实现了 fan-out 行为,因此您可以有多个事件使用者,但每个事件只会被处理一次。 Channel.receiveAsFlow 可以非常方便地将流公开为流。否则,SharedFlow 是事件总线实现的一个很好的候选者。请注意 replayextraBufferCapacity 参数。

,

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

覆盖 fun onCreated(savedInstance: Bundle?) { 工具栏控制器()

    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")
        }
    }
}

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...