【问题标题】:onResume does not worked in viewmodelonResume 在视图模型中不起作用
【发布时间】:2020-10-15 12:43:36
【问题描述】:

我的数据仅在创建时才被获取...我正在使用 viewmodel...当按下返回按钮时它不会更新以前的数据..onresume 在此不起作用...

我提到了这个,但这些都没有帮助--> Reacting to activity lifecycle in ViewModel

我需要帮助

提前致谢

活动:--

class MyAccount : BaseClassActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.myaccount)



    var mActionBarToolbar = findViewById<androidx.appcompat.widget.Toolbar>(R.id.toolbartable);
    setSupportActionBar(mActionBarToolbar);
  setEnabledTitle()


    val resetbutton=findViewById<Button>(R.id.resetpwd)
    resetbutton.setOnClickListener {
        val i=Intent(applicationContext,
            ResetPasswordActivity::class.java)
        startActivity(i)
    }
    val editbutton=findViewById<Button>(R.id.editdetail)
    editbutton.setOnClickListener {
        val i=Intent(applicationContext, EditProfile::class.java)
        startActivity(i)
    }

  hello()
}

override fun onResume() {
    super.onResume()
  hello()

}

fun hello(){
    val first_name = findViewById<TextView>(R.id.firstname)
    val last_name = findViewById<TextView>(R.id.lastname)
    val emailuser = findViewById<TextView>(R.id.emailuser)
    val phone_no = findViewById<TextView>(R.id.phone_no)
    val birthday = findViewById<TextView>(R.id.birthday)
    val image=findViewById<ImageView>(R.id.imageprofile)


    val model = ViewModelProvider(this)[MyAccountViewModel::class.java]

    model.viewmodel?.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 onOptionsItemSelected(item: MenuItem): Boolean {
    return when (item.itemId) {
        android.R.id.home -> {
            NavUtils.navigateUpFromSameTask(this)

            true
        }
        else -> super.onOptionsItemSelected(item)
    }
}}

视图模型:--

class MyAccountViewModel(context: Application) :AndroidViewModel(context),LifecycleObserver{
private var MyAccountViewModels: MutableLiveData<My_account_base_response>? = null
val viewmodel: MutableLiveData<My_account_base_response>?
    get() {
        if (MyAccountViewModels == null) {
            MyAccountViewModels = MutableLiveData<My_account_base_response>()
            loadviewmodel()
        }
        return MyAccountViewModels

    }

private fun loadviewmodel(){
    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)


            }

            override fun onResponse(
                call: Call<My_account_base_response>,
                response: Response<My_account_base_response>
            ) {
                var res = response

                if (res.body()?.status == 200) {
                    MyAccountViewModels!!.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)
                    }
                }
            }
        })
}}

【问题讨论】:

  • if (MyAccountViewModels == null) 然后你 MyAccountViewModels = MutableLiveData&lt;My_account_base_response&gt;() 这意味着当恢复发生时,它不会为空并且你会返回 else MyAccountViewModels
  • 我正在返回返回MyAccountViewModels@cutiko

标签: android kotlin viewmodel android-livedata lifecycle


【解决方案1】:

这里有很多问题,所以让我尽可能多地为您提供重构的代码和解释..

活动:

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)
        }
    }
}

关于你的活动课的几点说明:

  1. 您不需要每次都findViewById,只需在onCreate 期间执行一次或懒惰地执行。 (仅供参考,考虑使用 kotlin 合成或视图绑定或数据绑定)

  2. 仅在 onCreate 方法期间初始化您的 viewModel(这是最好的方法)

  3. 还从ViewModel 观察您的LiveData 一次,它也应该来自onCreate,因为它是活动的入口点,除了配置更改之外,此方法仅调用一次。因此,在那里观察它是安全的,而不是在onResume 期间观察它,onResume 在活动生命周期中将被多次调用。 (您的代码无法正常工作的主要问题,因此作为修复,您只能在恢复期间从ViewModel 调用您的 API 方法)

视图模型:

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. 不要在创建 LiveData 的同时进行初始 API 调用,在大多数情况下可以这样做,但如果您在响应该调用时更新 LiveData,那么最好像在 init 块期间那样单独进行.

  2. 最好不要让 Ui (Activity/Fragments) 直接修改 LiveDatas 的 ViewModel。所以,这是一个很好的迹象,您通过将私人 MutableLiveData 暴露为公共 LiveData 来遵循这种模式,但请按照建议正确执行。

  3. 旁注:您的视图模型不需要是LifecycleObserverLifecycleObserver 用于一些自定义类/组件,这些类/组件需要通过独立地静默观察/依赖于活动生命周期来自行管理。这不是ViewModel 的用例。


我发现您的代码无法正常工作的唯一原因是因为您在调用 hello() 方法的 onResume 方法中一遍又一遍地创建和观察 ViewModelLiveData 作为新对象.

如果有什么不明白或遗漏的地方,请告诉我。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2021-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多