【问题标题】:Making changes to LiveData to "redo" work in ViewModel在 ViewModel 中更改 LiveData 以“重做”工作
【发布时间】:2017-08-14 10:24:24
【问题描述】:

所以,我刚刚开始尝试使用 LiveData - 我正忙于一个新项目,我正在使用 ViewModelLiveData - 以及我用来获取数据的一些 RESTFul 服务,它们不带参数并返回一些数据。

带有LiveData 的 MVVM 范例的典型设置如下所示:

public class MyActivity extends AppCompatActivity {
    public void onCreate(Bundle savedInstanceState) {
        MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
        model.getUsers().observe(this, users -> {
            // update UI
        });
    }
}

现在,当我们离开这个活动,去一个新的活动,通过使用意图或其他方式,而不是按下后退按钮(所以,finalize 没有被调用) - 然后回到@987654328 @ - 我们当然不会再次获取users,因为我们应该仍然拥有该数据。

但是,如果我们确实想再次获取它们怎么办?

据我所见,正确执行此操作的唯一方法似乎是在 getUsers() LiveData 对象上调用“setValue”

类似这样的:

public class MyActivity extends AppCompatActivity {
    public void onResume() {
     viewModel.setActive(true); 
    }
}

ViewModel 看起来像这样:

  private final MutableLiveData<Boolean> activeLiveData = new MutableLiveData<>();

 ViewModel(ViewModelRepo repo){
      this.repo = repo;

      results = Transformations.switchMap(activeLiveData, active ->{
        if(active){
          return repo.getUsers();
        }else {
          return AbsentLiveData.create(); //"Null live data"
        }
      });
  }

   LiveData<Users>> getUsers() {
    return results;
  }

 //This could be called "update" with no params 
  void setActive(boolean active) {
    activeLiveData.setValue(active);
  }

我决定这样做的一个原因是因为 Google 不希望我们这样做:

class MyViewModel extends ViewModel {
    private final PostalCodeRepository repository;
    public MyViewModel(PostalCodeRepository repository) {
       this.repository = repository;
    }

    private LiveData<String> getPostalCode(String address) {
       // DON'T DO THIS
       return repository.getPostCode(address);
    }
}

出于这个原因:

如果这是实现,则 UI 需要从 以前的 LiveData 并每次重新注册到新实例 他们调用 getPostalCode()。此外,如果重新创建 UI,它 触发对 repository.getPostCode() 的另一个调用,而不是使用 上一次调用的结果。

有没有更好的方法让ViewModel“重做”它的repo.getUsers() 调用?也许我可以只做一个方法,说“更新()”而不是“活动”,但仍然 - 它以不同的方式做同样的事情。

【问题讨论】:

    标签: android mvvm android-architecture-components android-viewmodel


    【解决方案1】:

    好吧,您正在 ViewModel 的创建者中进行获取,这会将事物锁定到位。通常他们会建议在 getter 中获取数据,如果数据不存在的话。

    所以一个不错的选择是首先使用常规模式:

      private MutableLiveData<Users> users = null;
    
     ViewModel(ViewModelRepo repo){
          this.repo = repo;
      }
    
       LiveData<Users> getUsers() {
        if (users = null) {
          fetchUsers();
        }
        return users;
      }
    
      public void fetchUsers() {
        users.postValue(repo.getUsers());
      }
    

    然后从您的 Activity/Fragment 中,每当您觉得有必要“刷新用户”时,您只需致电 viewModel.fetchUsers();

    【讨论】:

    • 我有一个类似的用例,但我在“users.postValue()...”方法中收到警告,因为我在存储库中使用 LiveData> 而不是 List。关于如何解决的任何想法?
    猜你喜欢
    • 1970-01-01
    • 2022-01-17
    • 2019-05-03
    • 2022-01-14
    • 1970-01-01
    • 2018-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多