Search code examples
androidkotlinmvvmviewmodelandroid-livedata

getResponse From ViewModel Live Data


I was trying to get response from viewModel But, I am having hard time to use the response data on another activity to display it on a text view. I have already setup the backend for the repo's and interfaces, data classes etc...

Thank you!!!

// View Model


class HomeActivityViewModel : ViewModel() {

    lateinit var createPostLiveData: MutableLiveData<PostResponseData?>

    init {
        createPostLiveData = MutableLiveData()
    }
    fun getPostLiveObserver(): MutableLiveData<PostResponseData?> {
        return createPostLiveData
    }

    fun createPostData(postdata: PostData) {
        val retroService = RetrofitApiFactory.retroInstance().create(ChefApi::class.java)

        val call = retroService.postData(postdata)

        call.enqueue(object : Callback<PostResponseData> {
            override fun onResponse(
                call: Call<PostResponseData>,
                response: Response<PostResponseData>
            ) {
                if (response.isSuccessful) {
                    createPostLiveData.postValue(response.body())
                    var text = response.body()!!.choices[0].text
                    Log.d("response", text) // only shows the one in the viewModel


                } else {
                    createPostLiveData.postValue(null)
                    Log.d("failed", response.errorBody().toString())
                }

            }

            override fun onFailure(call: Call<PostResponseData>, t: Throwable) {
                Log.d("failed", t.message.toString())
                createPostLiveData.postValue(null)
            }

        })

    }
}

Activity.kt

class HomeActivity : AppCompatActivity() {
    lateinit var mAuth: FirebaseAuth
    lateinit var viewModel: HomeActivityViewModel
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_home_actvity)

        mAuth = FirebaseAuth.getInstance()

        initViewModel()

        generate.setOnClickListener {
            createPost()
        }
        logout.setOnClickListener {
            logoutUser()
        }
    }

    private fun createPost() {
        // creating a post
        val prompt = "Some string..." 
        val postdata = PostData(120, prompt, 0.3, 1.0, 0.0)
        viewModel.createPostData(postdata)
    }

    private fun initViewModel() {
        // initialize view model
        viewModel = ViewModelProvider(this).get(HomeActivityViewModel::class.java)
        viewModel.getPostLiveObserver().observe(this, Observer<PostResponseData?> {
            if (it == null) {
                Toast.makeText(this@HomeActivity, "Failed to post data", Toast.LENGTH_SHORT).show()
            } else {
                Toast.makeText(this@HomeActivity, "Successfully posted data", Toast.LENGTH_SHORT)
                    .show()
            }
        })
    }

    private fun logoutUser() {
        mAuth.signOut()
        updateUI()
    }

    private fun updateUI() {
        val intent = Intent(this@HomeActivity, MainActivity::class.java)
        startActivity(intent)
        finish()
    }

Solution

  • Try to change your HomeActivityViewModel class and add a LiveData object to it:

    class HomeActivityViewModel : ViewModel() {
    
        var _createPostLiveData: MutableLiveData<PostResponseData?>()
        // Live data instance
        val createPostLiveData
            get() = _createPostLiveData
    
        fun createPostData(postdata: PostData) {
            val retroService = RetrofitApiFactory.retroInstance().create(ChefApi::class.java)
    
            val call = retroService.postData(postdata)
    
            call.enqueue(object : Callback<PostResponseData> {
                override fun onResponse(
                    call: Call<PostResponseData>,
                    response: Response<PostResponseData>
                ) {
                    if (response.isSuccessful) {
                        // Update live data value
                        _createPostLiveData.value = response.body()
                        var text = response.body()!!.choices[0].text
                        Log.d("response", text) // only shows the one in the viewModel
    
    
                    } else {
                        // Update live data value
                        _createPostLiveData.value = null
                        Log.d("failed", response.errorBody().toString())
                    }
    
                }
    
                override fun onFailure(call: Call<PostResponseData>, t: Throwable) {
                    Log.d("failed", t.message.toString())
                    // Update live data value
                    _createPostLiveData.value = null
                }
            })
        }
    }
    

    You should then be able to observe the LiveData instance in your Activity:

    class HomeActivity : AppCompatActivity() {
    
        lateinit var mAuth: FirebaseAuth
        // Initialize view model in declaration
        private val viewModel: HomeActivityViewModel by viewModels()
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_home_actvity)
    
            mAuth = FirebaseAuth.getInstance()
    
            // Observe for `createPostLiveData` changes
            viewModel.createPostLiveData.observe(this) {
                if (it == null) {
                    Toast.makeText(this@HomeActivity, "Failed to post data", Toast.LENGTH_SHORT).show()
                } else {
                    Toast.makeText(this@HomeActivity, "Successfully posted data", Toast.LENGTH_SHORT)
                        .show()
                }
            }
    
            generate.setOnClickListener {
                createPost()
            }
            logout.setOnClickListener {
                logoutUser()
            }
        }
    
        private fun createPost() {
            // creating a post
            val prompt = "Some string..." 
            val postdata = PostData(120, prompt, 0.3, 1.0, 0.0)
            viewModel.createPostData(postdata)
        }
    
        ...