【问题标题】:How to get response variable from viewModelScope Android如何从 viewModelScope Android 获取响应变量
【发布时间】:2020-10-09 10:36:54
【问题描述】:

在我的 Android 项目中,我需要在另一个片段中使用我的视图模型的一个响应。但是,每当我尝试获取该值时,它始终为空。我试图从它自己的带有 livedata 的片段中获取它并且它有效!但另一个片段就不一样了。这是我的具有响应的视图模型代码;

package com.tolgahantutar.bexworkfloww.ui.auth

import android.content.Intent
import android.view.View
import android.widget.Toast
import androidx.hilt.lifecycle.ViewModelInject
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.tolgahantutar.bexworkfloww.data.network.repositories.AuthorizeSessionRepository
import com.tolgahantutar.bexworkfloww.data.network.repositories.GetDomainRepository
import com.tolgahantutar.bexworkfloww.data.network.repositories.GetUserRepository
import com.tolgahantutar.bexworkfloww.data.network.responses.GetUserResponse
import com.tolgahantutar.bexworkfloww.ui.home.HomeActivity
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

class AuthViewModel @ViewModelInject constructor (
   private val authorizeSessionRepository: AuthorizeSessionRepository,
   private val getDomainRepository: GetDomainRepository,
   private val getUserRepository: GetUserRepository
):ViewModel() {

    var userName :String?=null
    var password: String ? = null
    val isLoading = MutableLiveData<Boolean>()
    private val location = "bexfatest.saasteknoloji.com"
    val isSuccessfull = MutableLiveData<Boolean>()
    var getUserResponseMutable = MutableLiveData<GetUserResponse>()
    fun onClickUserLogin(view: View){
        val sessionID = 0
        val authorityID = 0
        val loginType = "System"

        viewModelScope.launch {
                if(!(userName==null||password==null)){
                isLoading.value = true

                    val authResponse = userLogin(sessionID,authorityID,userName!!,password!!,loginType)

                if(authResponse.Result){
                    isLoading.value=false
                    val domainResponse=getDomain(location)
                    **`val getUserResponse`** = getUser(authResponse.authorizeSessionModel!!.ID,"Bearer "+domainResponse.getDomainModel.ApiKey)
                    if (getUserResponse.result){
                        isSuccessfull.value=true
                        getUserResponseMutable.value=getUserResponse
                    }
                    //Toast.makeText(view.context, "Login Successfull", Toast.LENGTH_LONG).show()
                    val intent = Intent(view.context,HomeActivity::class.java)
                    view.context.startActivity(intent)
                }else{
                    isLoading.value=false
                    Toast.makeText(view.context, "Login Failed!!", Toast.LENGTH_LONG).show()
                }
           }
            else{
                Toast.makeText(view.context, "Kullanıcı adı ve şifre boş bırakılamaz!!", Toast.LENGTH_SHORT).show()
            }
        }
}


suspend fun userLogin(
SessionID : Int,
AuthorityID: Int,
UserName: String,
Password : String,
LoginType: String
)= withContext(Dispatchers.IO){authorizeSessionRepository.userLogin(SessionID, AuthorityID, UserName, Password, LoginType)}

suspend fun getUser(
id: Int,
authorization : String
)= withContext(Dispatchers.Main){getUserRepository.getUser(id,authorization)}

suspend fun getDomain(
Location: String
)= withContext(Dispatchers.IO){getDomainRepository.getDomain(Location)}

}

我需要像这样在我的地址簿片段中获取 getUserResponse 变量;

package com.tolgahantutar.bexworkfloww.ui.addressbook

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.viewModels
import androidx.lifecycle.Observer
import com.tolgahantutar.bexworkfloww.R
import com.tolgahantutar.bexworkfloww.ui.auth.AuthViewModel
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class AdressBookFragment : Fragment() {
    private val addressBookViewModel : AdressBookViewModel by viewModels()
    private val authViewModel : AuthViewModel by viewModels()

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.adress_book_fragment, container, false)
    }
    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        //addressBookViewModel.getContact(2,authViewModel.userResponseDelegate!!.getUserValue.apiKey)
     authViewModel.getUserResponseMutable.observe(viewLifecycleOwner, Observer {
         if (it.result){
             Toast.makeText(requireContext(), "asdadasd", Toast.LENGTH_SHORT).show()
         }
     })
        addressBookViewModel.isSuccessfull.observe(viewLifecycleOwner, Observer {
            if (it){
                Toast.makeText(requireContext(), "ContactList Get Successfully", Toast.LENGTH_SHORT).show()
            }
        })
    }
}

但是观察总是空的,我怎样才能在我的 AddressBookFragment 中获取 getUserResponse ??

【问题讨论】:

    标签: android kotlin android-fragments mvvm response


    【解决方案1】:

    当您离开 AuthFragment(我假设您已经拥有)时,AuthViewModel 很可能会被破坏,因此您的 AdressBookFragment 正在获取 ViewModel 的新实例,它不会保留之前的任何数据屏幕。

    我建议您将来自 AuthViewModel 的结果存储到存储库或其他一些全局状态对象中,然后从那里检索它。

    ViewModel 保存屏幕所需的临时数据,但用户是否经过身份验证对整个应用程序很重要,而不仅仅是单个屏幕。因此,它应该存储在与整个应用程序一样长的地方,并且可以从任何地方访问,例如存储库。

    【讨论】:

    • 先生,您真棒!你解释得很容易理解,它给了我一个想法,所以我解决了这个问题。感谢您的精彩回答!
    【解决方案2】:
    private val authViewModel : AuthViewModel by viewModels()
    

    等价于

    private val viewModel by lazy {
        ViewModelProvider(this).get(AuthViewModel::class.java)
    }
    

    如您所见,this 被传递为viewModelStoreOwner。 因为我猜你确实在另一个片段中使用AdressBookFragment 作为viewModelStoreOwner,所以你正在这个片段中创建一个新的viewmodel

    您可能需要使用时获得的共享视图模型

    private val viewModel by lazy {
        ViewModelProvider(requireActivity()).get(AuthViewModel::class.java)
    }
    

    在两个片段中

    【讨论】:

    • 我明白了你的意思,但现在我意识到第一个所有者不是片段而是活动。我也尝试过这种方式,但它仍然无法正常工作
    • 你的片段是否存在于同一个活动中?
    • 是的,他们确实做到了
    • 您是否还更改了其他片段中视图模型的初始化?它还需要作为 viewmodelstoreowner 的活动
    • 我通过创建一个单例存储库类解决了这个问题,然后在我的片段中调用该类。谢谢你的回答
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-19
    • 1970-01-01
    • 2013-07-20
    • 1970-01-01
    • 1970-01-01
    • 2016-08-08
    相关资源
    最近更新 更多