【问题标题】: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);       
}

在这种情况下,最好的方法是什么?

【问题讨论】:

  • 您可以使用常规回调接口。

标签: java android android-mvvm android-toast android-snackbar


【解决方案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 还是falsedoc
  • 不是理想的模式 - 一旦视图(活动/片段)从后台恢复,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()
     }
 })

【讨论】:

  • 出色的解决方案。这会在屏幕旋转和其他生命周期发生变化时考虑在内。
猜你喜欢
  • 2015-01-03
  • 2020-11-21
  • 2021-11-06
  • 1970-01-01
  • 2015-11-07
  • 2015-02-12
  • 2015-10-03
  • 1970-01-01
相关资源
最近更新 更多