Android Fragments 从button.setOnClickListener调用一个API,并导航到另一个Fragment

of1yzvn4  于 2023-06-23  发布在  Android
关注(0)|答案(1)|浏览(96)

我是Kotlin的新手,需要一些指导。
我有一个片段,在onCreateView中我有一个按钮,使用setOnClickListener。
我的onCreateView:

override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        binding = DataBindingUtil.inflate(inflater, R.layout.fragment_login, container, false)
        val view = binding.root
        sharedViewModel.setAppVersion(BuildConfig.VERSION_NAME)
        sharedViewModel.setFlavor(BuildConfig.FLAVOR)
        binding.apply { viewModel = loginViewModel }
        binding.apply { paramViewModel = sharedViewModel }
        // Inflate the layout for this fragment
         with(binding) {
             loginButton.setOnClickListener {
                 it
                 if (checkUsernamePassword()) {
                     callLoginApi(username.text.toString(), password.text.toString())
                     if (sessionKey.isNotEmpty()) {
                         Navigation.findNavController(it)
                             .navigate(R.id.action_loginFragment_to_landingPageFragment)
                     }
                 }
             }
         }
        return view
    }

单击按钮调用API:

private fun callLoginApi(_username: String, _password: String) {

    val login = LoginRequest(_username, _password)
    val retrofit = ServiceBuilder.buildService(RestApiInterface::class.java)

    retrofit.sendReq(login).enqueue(
        object : retrofit2.Callback<LoginResponse> {
            override fun onResponse(
                call: Call<LoginResponse>,
                response: Response<LoginResponse>
            ) {
                if (response.body()?.sessionKey?.isNotEmpty() == true) {
                    sessionKey = response.body()?.sessionKey.toString()
                    // displays a toast with session key
                    Toast.makeText(
                        activity,
                        response.body()?.sessionKey,
                        Toast.LENGTH_LONG
                    ).show()

                    //sharedViewModel.setSessionKey(response.body()?.sessionKey.toString())
                } else
                    Toast.makeText(
                        activity,
                        response.body()?.message,
                        Toast.LENGTH_LONG
                    ).show()
            }
            override fun onFailure(call: Call<LoginResponse>, t: Throwable) {
                TODO("Not yet implemented")
            }
        })
}

API调用返回一个会话密钥,我存储了它,但问题是当单击按钮时,会话密钥被返回,但按钮没有导航到我需要的下一个片段。我必须再次点击按钮,然后它导航到片段,但也调用API再次,我得到一个新的会话密钥。
有谁知道我哪里错了,我错过了什么吗?

new9mtju

new9mtju1#

API调用代码不是同步的,因此这意味着队列中的代码块将比单击侦听器代码块中的其余代码更晚执行。
你可以这样想:
1.单击监听器被调用
1.进行API调用(此执行转到后台)

  1. click监听器代码执行完毕,跳过if块(由于sessionKey仍然为空,API调用尚未完成!)
  2. API调用完成并设置sessionKey
    当您第二次单击时,sessionKey现在不是空的,因为API调用已经完成,导航开始了。
    为了解决这个问题,你必须在retrofit2.Callback中创建某种回调函数来进行导航,或者调用retrofit2.Callback块中的导航代码。

相关问题