【问题标题】:When to use MutableLiveData and LiveData何时使用 MutableLiveData 和 LiveData
【发布时间】:2019-09-18 18:00:43
【问题描述】:

何时使用MutableLiveDataLiveData表示使用方法的区域:

MutableLiveData<User> getUser() {
    if (userMutableLiveData == null) {
        userMutableLiveData = new MutableLiveData<>();
    }
    return userMutableLiveData;
}

以及何时使用它,

LiveData<User> getUser() {
    if (userMutableLiveData == null) {
        userMutableLiveData = new MutableLiveData<>();
    }
    return userMutableLiveData
}

【问题讨论】:

  • 基本上,您将它作为LiveData 暴露给UI (Activity/Fragment) 因为它不能直接修改它并将它作为MutableLiveData 暴露给存储库(如果在项目中使用).
  • 请举个简单的例子让我明白

标签: android android-architecture-components android-livedata


【解决方案1】:

LiveData 没有公共方法来修改其数据。

LiveData<User> getUser() {
    if (userMutableLiveData == null) {
        userMutableLiveData = new MutableLiveData<>();
    }
    return userMutableLiveData
}

您不能像getUser().setValue(userObject)getUser().postValue(userObject) 那样更新它的值

因此,当您不想修改数据时,请使用 LiveData 如果您想稍后修改数据,请使用MutableLiveData

【讨论】:

  • 您所说的我们不能错误地更新实时数据值。 LiveDate 不是同步的,而是同步的可变实时数据,并且还能够使用其 postValue 方法从 Worker 线程调用观察者。因此,当您不希望修改数据时,请使用 LiveData 如果您想稍后修改数据,请使用 MutableLiveData` 这个不正确的说法。 stackoverflow.com/questions/46814158/…
  • 我很不理解你的评论,链接也重复了同样的信息。 LiveData 是一个具有受保护的setValuepostValue 方法的抽象类,应该用于限制活动或片段的修改。您能否提供一个示例,您可以使用setValuepostValue 更新LiveData 值?
  • 但是,你不能把返回的 LiveData 转换成 MutableLiveData 吗?
  • MVVM 新手在这里。我了解到LiveDatathe sole way 用于ViewModelView 通信。那么不可变的LiveData 有什么意义呢?
【解决方案2】:

假设您遵循 MVVM 架构,并将 LiveData 作为从 ViewModelActivity 的可观察模式。这样您就可以将变量设置为 LiveData 对象暴露给 Activity,如下所示:

class MyViewModel : ViewModel() {
    // LiveData object as following
    var someLiveData: LiveData<Any> = MutableLiveData()

    fun changeItsValue(someValue: Any) {
        (someLiveData as? MutableLiveData)?.value = someValue
    }
}

现在在Activity 部分,您可以观察LiveData 但要进行修改,您可以从ViewModel 调用方法,如下所示:

class SomeActivity : AppCompatActivity() {
    // Inside onCreateMethod of activity
    val viewModel = ViewModelProviders.of(this)[MyViewModel::class.java]
    viewModel.someLiveData.observe(this, Observer{
        // Here we observe livedata
    })
    viewModel.changeItsValue(someValue) // We call it to change value to LiveData
    // End of onCreate
}

【讨论】:

  • @c0ming 通过在 ViewModel 中创建两个对象来实现此目的的另一种方法。 MutableLiveData 对象可以是私有的并通过 setter 方法进行操作,而公共对象可以从上面的私有对象重新分配 LiveData
  • @JeelVankhede 说得对,我的朋友,这是 Google 开发人员在 Udacity 官方网站上推荐的方式。这是封装我们不想让我们的类编辑的信息的方法。查看课程:classroom.udacity.com/courses/ud9012
【解决方案3】:

我们应该返回 LiveData 以防止视图(或其他观察者)意外修改值。

拥有:

    LiveData<User> getUser() {
       if (userMutableLiveData == null) {
           userMutableLiveData = new MutableLiveData<>();
       }
       return userMutableLiveData
    }

你不能在你的活动/片段中写:getUser().setValue(...)。这使您的代码不易出错。

【讨论】:

    【解决方案4】:

    LiveData 没有公开可用的方法来更新存储的数据。 MutableLiveData 类公开了setValue(T)postValue(T) 方法,如果您需要编辑存储在LiveData 对象中的值,则必须使用这些方法。通常MutableLiveData 用于ViewModel,然后ViewModel 只向观察者公开不可变的LiveData 对象。 请看看这个reference

    【讨论】:

      【解决方案5】:

      在单独的类中使用 MutableLiveData 的最佳方法 喜欢

      public class SharedViewModel extends ViewModel {
      private MutableLiveData<CharSequence>text = new MutableLiveData<>();
      
      public void setText(CharSequence input)
      {
          text.setValue(input);
      }
      
      public LiveData<CharSequence> getText(){
          return text;
      
      }
      }
      

      Livedata 用在 Fragment Like 中

      private SharedViewModel viewModel;
      
      @Override
      public void onActivityCreated(@Nullable Bundle savedInstanceState) {
              super.onActivityCreated(savedInstanceState);
              //No Need to initate further
              viewModel = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
              viewModel.getText().observe(getViewLifecycleOwner(), new Observer<CharSequence>() {
                  @Override
                  public void onChanged(@Nullable CharSequence charSequence) {
                      editText.setText(charSequence);
                  }
              });
          }
      

      在片段类中是这样的

      public class FragmentA extends Fragment {
          private SharedViewModel viewModel;
          private EditText editText;
          @Nullable
          @Override
          public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
              View v = inflater.inflate(R.layout.fragment_a, container, false);
              editText = v.findViewById(R.id.edit_text);
              Button button = v.findViewById(R.id.button_ok);
              button.setOnClickListener(new View.OnClickListener() {
                  @Override
                  public void onClick(View v) {
                      viewModel.setText(editText.getText());
                  }
              });
              return v;
          }
          @Override
          public void onActivityCreated(@Nullable Bundle savedInstanceState) {
              super.onActivityCreated(savedInstanceState);
              viewModel = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
              viewModel.getText().observe(getViewLifecycleOwner(), new Observer<CharSequence>() {
                  @Override
                  public void onChanged(@Nullable CharSequence charSequence) {
                      editText.setText(charSequence);
                  }
              });
          }
      }
      

      【讨论】:

        【解决方案6】:

        当您不想修改它时使用 LiveData,因为 setValue()postValue() 等方法不是 public 。实时数据通过在内部调用它们来照顾自己。

        在 MutableLiveData 中 setValue() postValue() 是公开的,即公开的。您可以通过调用这些方法来更改设置值。

        在此处查找更多详细信息: https://blog.mindorks.com/livedata-setvalue-vs-postvalue-in-android

        【讨论】:

          【解决方案7】:

          为了获得最佳实践、可读性和避免错误容易出错,就像 Kotlin 中的 MutableListList 一样。使用 Mutable 是当您希望修改其数据或希望对其重新分配新值时。

          当我们想要使其值可写或可以随时更改时,我们使用MutableLiveData

          当我们只想阅读和收听MutableLiveData 所做的任何更新时,我们会使用LiveData。因此我们有这种代码作为示例

          private var filterAsset = MutableLiveData<String>().apply{
                  value = "Empty"
              }
          
              //public method to set a new value on filterAsset
              fun setFilterData(assetName: String){
                  filterAsset.value = assetName
              }
          
          // We can use this to listen on any updates from filterAsset
          val assetFilterUpdates: LiveData<String> = filterAsset
          
          
          // Inside your Fragment/Activity
          // You can listen to the update in Fragment or Activity like this 
          yourViewModel.assetFilterUpdates.observe(viewLifecycleOwner, { value ->
          
                      // Use the updated value here
          
                  })
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2018-11-29
            • 1970-01-01
            • 1970-01-01
            • 2020-10-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多