Android:MVVM 是不是可以显示来自 ViewModel 的消息(toast/snackbar 等)
Posted
技术标签:
【中文标题】Android:MVVM 是不是可以显示来自 ViewModel 的消息(toast/snackbar 等)【英文标题】:Android: MVVM is it possible to display a message (toast/snackbar etc.) from the ViewModelAndroid:MVVM 是否可以显示来自 ViewModel 的消息(toast/snackbar 等) 【发布时间】:2019-04-28 07:33:11 【问题描述】:我想知道在 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)
);
还有我的活动:
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);
在这种情况下,最好的方法是什么?
【问题讨论】:
您可以使用常规回调接口。 【参考方案1】:使用 LiveData 在视图模型(活动/片段)中显示 Toast/snackbar 消息。
步骤:
将 LiveData 添加到您的视图模型中 View 只是观察 LiveData 和更新视图相关的任务例如:
在视图模型中:
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
)
【讨论】:
对于那些不熟悉 Kotlin 语法的人来说,安全调用运算符?.
将运行无论状态是true
还是false
。 doc
不是理想的模式 - 一旦视图(活动/片段)从后台恢复,LiveData 会发出最后一个值,这意味着 Toast 或 Snackbar 将再次显示。我自己正在寻找一个使用 SingleLiveEvent 的好设计。【参考方案2】:
我们可以使用SingleLiveEvent
类作为解决方案。但它是一个LiveData
,它只会发送一次更新。以我个人的经验,使用带有 MutableLiveData
的 Event Wrapper 类是最好的解决方案。
这是一个简单的代码示例。
第 1 步:
创建一个Event
类(这是一个样板代码,您可以在任何安卓项目中重复使用)。
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 类的顶部,定义一个带有包装器的 MutableLiveData
(我在这里使用了一个字符串,但您可以使用您需要的数据类型),以及一个相应的用于封装的实时数据。
private val statusMessage = MutableLiveData<Event<String>>()
val message : LiveData<Event<String>>
get() = statusMessage
第 3 步:
您可以像这样在ViewModel
的函数中更新状态消息:
statusMessage.value = Event("User Updated Successfully")
第四步:
编写代码以观察来自View
(活动或片段)的实时数据
yourViewModel.message.observe(this, Observer
it.getContentIfNotHandled()?.let
Toast.makeText(this, it, Toast.LENGTH_LONG).show()
)
【讨论】:
出色的解决方案。这会在屏幕旋转和其他生命周期发生变化时考虑在内。以上是关于Android:MVVM 是不是可以显示来自 ViewModel 的消息(toast/snackbar 等)的主要内容,如果未能解决你的问题,请参考以下文章
我可以在不使用gradle的情况下使用Xamarin.Android中的Android数据绑定库吗?不是MVVM for dotnet