簡體   English   中英

使用 Retrofit 在用戶注冊中實時數據返回舊響應然后新響應總是在吐司中

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

問題陳述:當我按下注冊按鈕注冊新用戶時,它會在實時數據的 toast 中顯示注冊成功響應,但是當我嘗試執行相同的按鈕觸發時,它再次顯示來自 API 的注冊成功響應消息,然后還顯示電話號碼存在響應API 吐司。 這也意味着實時數據返回舊響應。 那么我該如何解決這個遞歸實時數據響應返回問題呢?

這里是問題視頻鏈接以了解問題檢查這里https://drive.google.com/file/d/1-hKGQh9k0EIYJcbInwjD5dB33LXV5GEn/view?usp=sharing

需要阿根廷幫助

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

我的觀點 Model 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)
            })
        }
    }
}

我的注冊活動

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是一個 state 持有者,它並不是真的要用作事件 stream。 然而,有許多關於像這樣的主題的文章描述了可能的解決方案,包括從谷歌樣本中獲取的SingleLiveEvent實現。

但截至目前 kotlin 協程庫提供了更好的解決方案。 特別是,通道對於事件流非常有用,因為它們實現了扇出行為,因此您可以擁有多個事件消費者,但每個事件只會被處理一次。 Channel.receiveAsFlow可以非常方便地將 stream 公開為流。 否則, SharedFlow是事件總線實現的理想選擇。 請注意replayextraBufferCapacity參數。

您的 registerResponse 實時數據在按鈕單擊偵聽器內觀察,這就是它觀察兩次的原因! 您的 registerResponse 實時數據應觀察按鈕單擊偵聽器之外的數據 -

覆蓋 fun 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")
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM