Android:MVVM 是否可以显示来自 ViewModel 的消息(toast/snackbar 等)
Android: MVVM is it possible to display a message (toast/snackbar etc.) from the ViewModel
我想知道在 ViewModel 的视图中显示某种消息的最佳方法是什么。我的 ViewModel 正在进行 POST 调用并且 "onResult" 我想向用户弹出一条包含特定消息的消息。
这是我的视图模型:
public class RegisterViewModel extends ViewModel implements Observable {
.
.
.
public void registerUser(PostUserRegDao postUserRegDao) {
repository.executeRegistration(postUserRegDao).enqueue(new Callback<RegistratedUserDTO>() {
@Override
public void onResponse(Call<RegistratedUserDTO> call, Response<RegistratedUserDTO> response) {
RegistratedUserDTO registratedUserDTO = response.body();
/// here I want to set the message and send it to the Activity
if (registratedUserDTO.getRegisterUserResultDTO().getError() != null) {
}
}
});
}
还有我的Activity:
public class RegisterActivity extends BaseActivity {
@Override
protected int layoutRes() {
return R.layout.activity_register;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
AndroidInjection.inject(this);
super.onCreate(savedInstanceState);
ActivityRegisterBinding binding = DataBindingUtil.setContentView(this, layoutRes());
binding.setViewModel(mRegisterViewModel);
}
在这种情况下最好的方法是什么?
使用 LiveData.
在视图模型 (Activity/Fragment) 中显示 Toast/snackbar 消息
步骤:
- 将 LiveData 添加到您的视图模型中
- View只是观察LiveData和更新view相关的任务
例如:
在视图模型中:
var status = MutableLiveData<Boolean?>()
//In your network successfull response
status.value = true
在您的 Activity 或片段中:
yourViewModelObject.status.observe(this, Observer { status ->
status?.let {
//Reset status value at first to prevent multitriggering
//and to be available to trigger action again
yourViewModelObject.status.value = null
//Display Toast or snackbar
}
})
我们可以使用 SingleLiveEvent
class 作为解决方案。但它是一个只会发送一次更新的LiveData
。根据我个人的经验,使用事件包装器 class 和 MutableLiveData
是最好的解决方案。
这是一个简单的代码示例。
第 1 步:
创建一个 Event
class(这是一个样板代码,您可以在任何 android 项目中重复使用)。
open class Event<out T>(private val content: T) {
var hasBeenHandled = false
private set // Allow external read but not write
/**
* Returns the content and prevents its use again.
*/
fun getContentIfNotHandled(): T? {
return if (hasBeenHandled) {
null
} else {
hasBeenHandled = true
content
}
}
/**
* Returns the content, even if it's already been handled.
*/
fun peekContent(): T = content
}
第 2 步:
在你的 View Model class 的顶部,定义一个 MutableLiveData
with wrapper(我这里使用的是 String,但你可以使用你需要的数据类型),以及一个相应的 live 数据用于封装。
private val statusMessage = MutableLiveData<Event<String>>()
val message : LiveData<Event<String>>
get() = statusMessage
第 3 步:
您可以像这样在 ViewModel
的函数中更新状态消息:
statusMessage.value = Event("User Updated Successfully")
第 4 步:
编写代码以观察来自 View
(activity 或片段)
的实时数据
yourViewModel.message.observe(this, Observer {
it.getContentIfNotHandled()?.let {
Toast.makeText(this, it, Toast.LENGTH_LONG).show()
}
})
我想知道在 ViewModel 的视图中显示某种消息的最佳方法是什么。我的 ViewModel 正在进行 POST 调用并且 "onResult" 我想向用户弹出一条包含特定消息的消息。
这是我的视图模型:
public class RegisterViewModel extends ViewModel implements Observable {
.
.
.
public void registerUser(PostUserRegDao postUserRegDao) {
repository.executeRegistration(postUserRegDao).enqueue(new Callback<RegistratedUserDTO>() {
@Override
public void onResponse(Call<RegistratedUserDTO> call, Response<RegistratedUserDTO> response) {
RegistratedUserDTO registratedUserDTO = response.body();
/// here I want to set the message and send it to the Activity
if (registratedUserDTO.getRegisterUserResultDTO().getError() != null) {
}
}
});
}
还有我的Activity:
public class RegisterActivity extends BaseActivity {
@Override
protected int layoutRes() {
return R.layout.activity_register;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
AndroidInjection.inject(this);
super.onCreate(savedInstanceState);
ActivityRegisterBinding binding = DataBindingUtil.setContentView(this, layoutRes());
binding.setViewModel(mRegisterViewModel);
}
在这种情况下最好的方法是什么?
使用 LiveData.
在视图模型 (Activity/Fragment) 中显示 Toast/snackbar 消息步骤:
- 将 LiveData 添加到您的视图模型中
- View只是观察LiveData和更新view相关的任务
例如:
在视图模型中:
var status = MutableLiveData<Boolean?>()
//In your network successfull response
status.value = true
在您的 Activity 或片段中:
yourViewModelObject.status.observe(this, Observer { status ->
status?.let {
//Reset status value at first to prevent multitriggering
//and to be available to trigger action again
yourViewModelObject.status.value = null
//Display Toast or snackbar
}
})
我们可以使用 SingleLiveEvent
class 作为解决方案。但它是一个只会发送一次更新的LiveData
。根据我个人的经验,使用事件包装器 class 和 MutableLiveData
是最好的解决方案。
这是一个简单的代码示例。
第 1 步:
创建一个 Event
class(这是一个样板代码,您可以在任何 android 项目中重复使用)。
open class Event<out T>(private val content: T) {
var hasBeenHandled = false
private set // Allow external read but not write
/**
* Returns the content and prevents its use again.
*/
fun getContentIfNotHandled(): T? {
return if (hasBeenHandled) {
null
} else {
hasBeenHandled = true
content
}
}
/**
* Returns the content, even if it's already been handled.
*/
fun peekContent(): T = content
}
第 2 步:
在你的 View Model class 的顶部,定义一个 MutableLiveData
with wrapper(我这里使用的是 String,但你可以使用你需要的数据类型),以及一个相应的 live 数据用于封装。
private val statusMessage = MutableLiveData<Event<String>>()
val message : LiveData<Event<String>>
get() = statusMessage
第 3 步:
您可以像这样在 ViewModel
的函数中更新状态消息:
statusMessage.value = Event("User Updated Successfully")
第 4 步:
编写代码以观察来自 View
(activity 或片段)
yourViewModel.message.observe(this, Observer {
it.getContentIfNotHandled()?.let {
Toast.makeText(this, it, Toast.LENGTH_LONG).show()
}
})