onResume在视图模型中不起作用 [英] onResume does not worked in viewmodel
问题描述
仅当创建数据时才获取我的数据...使用viewmodel即时显示...当按后退按钮时它不更新以前的数据..onresume在此不起作用...
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...
我提到了这个,但没有一个帮助过> 在ViewModel中对活动生命周期进行反应
i refered this but none of those helped--> 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)
}
}}
viewmodel:-
viewmodel:--
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)
}
}
}
})
}}
推荐答案
这里有很多错误,因此,我将尽我所能为您提供重构的代码和解释.
There are bunch of things wrong here, so let me provide you refactored code and explanation as much as I would be able to..
活动:
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:
-
您不需要每次都
findViewById
,只需在onCreate
期间执行一次即可,也可以懒惰地执行. (仅供参考,我考虑使用Kotlin合成材料或视图绑定或数据绑定)
You don't need to
findViewById
everytime, just do it once duringonCreate
or do it lazily. (FYI consider using kotlin synthetics or view binding or data binding)
仅在onCreate
方法期间初始化您的viewModel
. (这是最好的方法)
Initialize your viewModel
during onCreate
method only. (That's the best way to do it)
也要从ViewModel
观察您的LiveData
,它也应该来自onCreate
,因为它是活动的入口点,除了配置之外,此方法仅被调用一次.因此,在那儿观察它是安全的,而不是在活动生命周期中多次调用onResume
期间观察它. (您的代码无法解决的主要问题,因此,您只能在恢复过程中从ViewModel
调用API方法)
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:
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)
}
}
}
})
}
}
-
不要在创建
LiveData
的同时进行初始API调用,在大多数情况下都可以这样做,但是如果要根据该调用的响应来更新LiveData
,则最好像这样单独进行在初始化块期间.
Don't make initial API call along with
LiveData
creation, it's okay to do in most of cases but if you're updatingLiveData
on response of that call then it's good to make it separately like during init block.
优良作法是不允许Ui (活动/片段)直接修改ViewModel
的LiveData
个.因此,这是您通过将私有MutableLiveData
公开为公共LiveData
而遵循这种模式的一个好兆头,但请按照建议正确执行.
It's good practice not to allow Ui (Activity/Fragments) to modify LiveData
s 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.
旁注:您的视图模型不必为LifecycleObserver
. LifecycleObserver
用于某些自定义类/组件,这些类/组件需要通过自己静默地观察/独立于活动生命周期来对其进行自我管理.那不是ViewModel
的用例.
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
.
我发现您的代码无法正常运行的唯一原因是,您正在创建&观察ViewModel
& LiveData
over&作为hello()
方法的新对象,再次调用了hello()
方法.
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.
这篇关于onResume在视图模型中不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!