首页 > 解决方案 > 如何从我的 POST 请求改造调用中获得对我的 Fragment 的响应

问题描述

我的目标是当我单击signUp-Button 并导航到verification-Fragment (如果 response.status 为 true时)从我的viewModel捕获或获取响应到我的signUp-Fragment中。

当我在我的 signUpFragment 中单击我的注册按钮时,会发出一个 POST 请求改造调用,并收到如下响应:

UserResponse(message=Sign up successful. A verfication code has been sent to your email address, payload=UserPayload(country=Nigeria, createdAt=2020-04-10T10:55:06.220Z, email=osehiproductengineer@gmail.com, id=5e90508a455f70002f19b42e, isVerified=false, name=osehiase ehilen, phone=07083372454, updatedAt=2020-04-10T10:55:06.220Z, v=0), status=200, token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI1ZTkwNTA4YTQ1NWY3MDAwMmYxOWI0MmUiLCJpYXQiOjE1ODY1MTYxMDYsImV4cCI6MTU4NjYwMjUwNn0.H_JhBQY-3PQ6Kqk7SS0cm8RP_1mzYlD987M66_LT0PU)

我使用 Log 看到了这个响应;响应没有到达我的 signUp-Fragment。

下面是我的存储库代码:

 class NetworkRepository(): BaseRepository() {

    val userApi = UserAPI()
    val authAPI = AuthAPI()
    val treeAPI = TreeAPI()
    val paymentAPI = PaymentAPI()
    val loginAPI = LoginAPI()

    val TAG = "NETWORK REPOSITORY"

    private val _networkState = MutableLiveData<NetworkState>()
    val networkState: LiveData<NetworkState>
        get() = _networkState




    //User
    suspend fun createUser(userBody: UserBody): UserResponse {
        var status = UserResponse()

//        Log.d("SIGNUP_RESPONSE2", "inside status:$status")
        withContext(Dispatchers.IO){
            try {
                status = userApi.addUserAsync(userBody).await()

//                Log.d("signup_Response3", "after the call:$status")
            }catch (t: Throwable){
                Log.e(TAG, t.message.toString())
            }
        }
        Log.d("SIGNUP_RESPONSE", "here is the $status")

        return status


    }
}

这是我的视图模型代码:

class UserViewModel : ViewModel(){
    private val repository = NetworkRepository()
    private val job = Job()
    private val scope = CoroutineScope(job + Dispatchers.Main)




    fun createUser(userBody: UserBody):UserResponse {
        var userPayload: UserResponse = UserResponse()
//        Log.d("USERVIEWMODEL_TOP", "the first response:$userPayload")
            scope.launch {
//            userPayload = repository.createUser(userBody)

                userPayload = repository.createUser(userBody)

//            Log.d("USERVIEWMODELCHCK", "speak now:$userPayload")
        }

//        Log.d("USERVIEWMODEL_RESPONSE", "check this userViewModelRes:$userPayload")
        return userPayload
    }
}

这是我的注册片段代码:

class SignUpFragment : Fragment() {

    private lateinit var viewModel: UserViewModel
    private lateinit var userBody: UserBody
     var captureStatus:UserResponse = UserResponse()


    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

        viewModel = ViewModelProvider(this).get(UserViewModel::class.java)



        return inflater.inflate(R.layout.fragment_sign_up, container, false)
    }


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




        signup_submit_btn.setOnClickListener {
            val response = sendUser()

//        Log.d("SIGNUP_FRAGMENTRES", "where is this response:$response")
            if (response.status == 200) {
                Log.d("SIGNUP_FRAGMENT", "wat is here:${response}")
                saveUserInfo(response)
                findNavController().navigate(R.id.action_signUpFragment_to_verificationFragment)
            } else {
                Toast.makeText(
                    this.context,
                    "${response.status}, ${response.message}",
                    Toast.LENGTH_SHORT
                ).show()
            }

        }

        signup_have_an_account.paintFlags = Paint.UNDERLINE_TEXT_FLAG

        signup_have_an_account.setOnClickListener {
            findNavController().navigate(R.id.action_signUpFragment_to_loginFragment)
        }

        signup_back_btn.setOnClickListener {
            findNavController().popBackStack()
        }
    }

    private fun sendUser(): UserResponse {
        var userBody: UserBody? = null
        //verification
        when {
            signup_email_input.editText!!.text.isEmpty() -> {
                signup_email_input.editText!!.error = "Email cannot be empty"
            }
            signup_phone_input.editText!!.text.isEmpty() -> {
                signup_phone_input.editText!!.error = "Phone cannot be empty"
            }
            signup_country_input.editText!!.text.isEmpty() -> {
                signup_country_input.editText!!.error = "Country cannot be empty"
            }
            signup_password_input.editText!!.text.isEmpty() -> {
                signup_password_input.editText!!.error = "Password cannot be empty"
            }
            signup_password_input.editText!!.text.length < 6 -> {
                signup_password_input.editText!!.error = "Password cannot be less than 6 characters"
            }
            signup_name_input.editText!!.text.isEmpty() -> {
                signup_name_input.editText!!.error = "Name cannot be empty"
            }
            else -> {
                val email = signup_email_input.editText!!.text.toString()
                val country = signup_country_input.editText!!.text.toString()
                val name = signup_name_input.editText!!.text.toString()
                val password = signup_password_input.editText!!.text.toString()
                val phone = signup_phone_input.editText!!.text.toString()
                userBody = UserBody(country, email, false, name, password, phone)
            }
        }




//        Log.d("USER REG", userBody.toString())



        return viewModel.createUser(userBody!!)


    }

    private fun saveUserInfo(userResponse: UserResponse) {
        this.activity?.let { Preferences.setEmail(it, userResponse.payload!!.email) }
        this.activity?.let { Preferences.saveAuthToken(it, userResponse.token!!) }
    }
}

标签: androidapiandroid-fragmentsretrofitviewmodel

解决方案


用一些虚拟对象实例化变量(如:statususerPayload),然后用其他方法的响应更改它,然后通过return函数返回它是不好的方法。您最好用 null 实例化它,并通过callback. 然后,如果您现在立即使您为空,则出现问题。


上述方法是您问题的根源。因为该createUser函数返回的是 DummyObject,而不是 Retrofit 的实际对象。要解决此问题,您需要从方法中删除return函数。createUser然后添加回调或高阶函数作为第二个参数。

这是创建用户时用作回调的高阶函数示例:

createUser在视图模型中

fun createUser(userBody: UserBody, onUserCreated: (UserResponse) -> Unit) {
    //Log.d("USERVIEWMODEL_TOP", "the first response:$userPayload")
    scope.launch {
        //userPayload = repository.createUser(userBody)

        val userPayload: UserResponse = repository.createUser(userBody)
        onUserCreated(userPayload)

        //Log.d("USERVIEWMODELCHCK", "speak now:$userPayload")
    }
}

为什么这样?因为scope.launch{...}类似于封闭环境,您必须以某种方式userPayload从大括号内获取scope.launch{ ... }。在您的解决方案中,您userPayload从外部返回,scope.launch{}对内部发生的事情一无所知{}

还要修改createUser存储库中的函数:

createUser在存储库中:

suspend fun createUser(userBody: UserBody): UserResponse {

    return withContext(Dispatchers.IO) {
        try {
            val status = userApi.addUserAsync(userBody).await()

            //Will be used as returend value.
            status
        } catch (t: Throwable) {

            //Will be used as returned value - in case of error.
            UserResponse()
        }
    }
}

为什么?原因同上。您正在从外部返回状态withContext(Dispatchers.IO) {}。所以由于我们想从内部返回一些东西withContext(Dispatchers.IO) {}——我们需要在之前添加 return 语句withContext。在这种情况下,最后一行try {}或最后一行catch{}(如果出现错误)将用作return之前语句的返回值withContext(Dispatchers.IO) {}

现在您应该能够通过createUser以下方式调用函数来接收片段中的响应:

分段

viewModel.createUser(userBody) { response ->
    if (response.status == 200) {
        Log.d("SIGNUP_FRAGMENT", "wat is here:${response}")
        saveUserInfo(response)
        findNavController().navigate(R.id.action_signUpFragment_to_verificationFragment)
    } else {
        Toast.makeText(
            this.context,
            "${response.status}, ${response.message}",
            Toast.LENGTH_SHORT
        ).show()
    }
}

推荐阅读