onResume does not worked in viewmodel

前端 未结 1 1125
-上瘾入骨i
-上瘾入骨i 2021-01-26 07:33

my data is fetched only when it is created...im using viewmodel...when press back button it doesnt update the previous data..onresume is not working in this...

i refered

相关标签:
1条回答
  • 2021-01-26 08:09

    There are bunch of things wrong here, so let me provide you refactored code and explanation as much as I would be able to..

    Activity:

    class MyAccount : BaseClassActivity() {
        private val mActionBarToolbar by lazy { findViewById<androidx.appcompat.widget.Toolbar>(R.id.toolbartable) }
        private val resetbutton by lazy { findViewById<Button>(R.id.resetpwd) }
        private val editbutton by lazy { findViewById<Button>(R.id.editdetail) }
        private val first_name by lazy { findViewById<TextView>(R.id.firstname) }
        private val last_name by lazy { findViewById<TextView>(R.id.lastname) }
        private val emailuser by lazy { findViewById<TextView>(R.id.emailuser) }
        private val phone_no by lazy { findViewById<TextView>(R.id.phone_no) }
        private val birthday by lazy { findViewById<TextView>(R.id.birthday) }
        private val image by lazy { findViewById<ImageView>(R.id.imageprofile) }
        lateinit var model: MyAccountViewModel
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.myaccount)
            setSupportActionBar(mActionBarToolbar)
            setEnabledTitle()
            model = ViewModelProvider(this)[MyAccountViewModel::class.java]
            resetbutton.setOnClickListener {
                val i = Intent(applicationContext, ResetPasswordActivity::class.java)
                startActivity(i)
            }
            editbutton.setOnClickListener {
                val i = Intent(applicationContext, EditProfile::class.java)
                startActivity(i)
            }
            model.accountResponseData.observe(this, object : Observer<My_account_base_response> {
                override fun onChanged(t: My_account_base_response?) {
                    first_name.setText(t?.data?.user_data?.first_name)
                    last_name.setText(t?.data?.user_data?.last_name)
                    emailuser.setText(t?.data?.user_data?.email)
                    phone_no.setText(t?.data?.user_data?.phone_no).toString()
                    birthday.setText(t?.data?.user_data?.dob).toString()
                    Glide.with(applicationContext)
                        .load(t?.data?.user_data?.profile_pic)
                        .diskCacheStrategy(DiskCacheStrategy.ALL)
                        .placeholder(R.drawable.ic_launcher_foreground)
                        .into(image)
                }
            })
        }
    
        override fun onResume() {
            super.onResume()
            model.loadAccountData()
        }
    
        override fun onOptionsItemSelected(item: MenuItem): Boolean {
            return when (item.itemId) {
                android.R.id.home -> {
                    NavUtils.navigateUpFromSameTask(this)
    
                    true
                }
                else -> super.onOptionsItemSelected(item)
            }
        }
    }
    

    Few notes on your activity class:

    1. You don't need to findViewById everytime, just do it once during onCreate or do it lazily. (FYI consider using kotlin synthetics or view binding or data binding)

    2. Initialize your viewModel during onCreate method only. (That's the best way to do it)

    3. Also observer your LiveData from ViewModel once, it should be also from the onCreate as it's the entry point to the activity and apart from config changes this method called only once. So, it's safe to observe it over there rather than during onResume which will be called multiple times during activity lifecycle. (The main issue your code wasn't working, so as a fix you only call your API method from ViewModel during resume)

    ViewModel:

    class MyAccountViewModel(context: Application) : AndroidViewModel(context) {
        private val _accountResponseData = MutableLiveData<My_account_base_response?>()
        val accountResponseData: MutableLiveData<My_account_base_response?>
            get() = _accountResponseData
    
        init {
            loadAccountData()
        }
    
        fun loadAccountData() {
            val token: String = SharedPrefManager.getInstance(getApplication()).user.access_token.toString()
            RetrofitClient.instance.fetchUser(token)
                .enqueue(object : Callback<My_account_base_response> {
                    override fun onFailure(call: Call<My_account_base_response>, t: Throwable) {
                        Log.d("res", "" + t)
                        _accountResponseData.value = null
                    }
    
                    override fun onResponse(
                        call: Call<My_account_base_response>,
                        response: Response<My_account_base_response>
                    ) {
                        var res = response
    
                        if (res.body()?.status == 200) {
                            _accountResponseData.value = response.body()
                        } else {
                            try {
                                val jObjError =
                                JSONObject(response.errorBody()!!.string())
                                Toast.makeText(
                                    getApplication(),
                                    jObjError.getString("user_msg"),
                                    Toast.LENGTH_LONG
                                ).show()
                            } catch (e: Exception) {
                                Log.e("errorrr", e.message)
                            }
                        }
                    }
                })
        }
    }
    
    1. Don't make initial API call along with LiveData creation, it's okay to do in most of cases but if you're updating LiveData on response of that call then it's good to make it separately like during init block.

    2. It's good practice not to allow Ui (Activity/Fragments) to modify LiveDatas of ViewModel directly. So, that's good sign you're following such pattern by having private MutableLiveData exposed as public LiveData, but do it correctly as suggested.

    3. Side note: Your view model doesn't need to be LifecycleObserver. LifecycleObserver is used for some custom class/component which needs to be managed by their self by silently observing/depending on activity lifecycle independently. That's not the use case of ViewModel.


    The only thing that I found why your code wasn't working correctly is because you were creating & observing ViewModel & LiveData over & over again as new objects from onResume method where you called hello() method.

    Let me know if something don't make sense or missing.

    0 讨论(0)
提交回复
热议问题