Ответ 1
РЕДАКТИРОВАТЬ с 2019 года: подождите, я думаю, вы могли бы решить эту проблему с MediatorLiveData.
Конкретно Transformations.switchMap
и некоторая дополнительная магия.
В настоящее время я использую
public void reloadTasks() {
if(liveResults != null) {
liveResults.removeObserver(this);
}
liveResults = getFilteredResults();
liveResults.observeForever(this);
}
Но если вы подумаете об этом, вы сможете решить эту проблему, не используя observeForever
за observeForever
, особенно если учесть, что switchMap
также делает нечто подобное.
Итак, нам нужен LiveData<SelectedOption>
который переключается на LiveData<PagedList<T>>
который нам нужен.
private MutableLiveData<String> filterText = new MutableLiveData<>();
private final LiveData<List<T>> data;
public MyViewModel() {
data = Transformations.switchMap(
filterText,
(input) -> {
if(input == null || input.equals("")) {
return repository.getData();
} else {
return repository.getFilteredData(input); }
}
});
}
public LiveData<List<T>> getData() {
return data;
}
Таким образом, фактические изменения от одного к другому обрабатываются MediatorLiveData. Если мы хотим кэшировать LiveDatas, мы можем сделать это в анонимном экземпляре, который мы передаем методу.
data = Transformations.switchMap(
filterText, new Function<String, LiveData<List<T>>>() {
private Map<String, LiveData<List<T>>> cachedLiveData = new HashMap<>();
@Override
public LiveData<List<T>> apply(String input) {
// ...
}
}
ОРИГИНАЛЬНЫЕ ОТВЕТЫ (они устарели)
РЕДАКТИРОВАТЬ: на самом деле. Хотя это имеет смысл для обычных LiveData<?>
, С помощью Paging вы можете на самом деле параметризовать Factory, а затем аннулировать источник данных и получить новый источник данных, оцененный бесплатно. Без воссоздания самого владельца запроса.
Таким образом, метод, упомянутый в другом ответе, является лучшим вариантом, когда вы используете пейджинг.
ОРИГИНАЛЬНЫЙ ОТВЕТ:
Вы знаете, как у вас есть адаптер, как это:
public class TaskAdapter
extends PagedListAdapter<Task, TaskAdapter.ViewHolder> {
public TaskAdapter() {
super(Task.DIFF_ITEM_CALLBACK);
}
В ViewModel вы настраиваете живой постраничный список и выставляете его:
private LiveData<PagedList<Task>> liveResults;
public TaskViewModel() {
liveResults = new LivePagedListBuilder<>(taskDao.tasksSortedByDate(),
new PagedList.Config.Builder() //
.setPageSize(20) //
.setPrefetchDistance(20) //
.setEnablePlaceholders(true) //
.build())
.setInitialLoadKey(0)
.build();
Затем вы наблюдаете постраничный список в ViewModel и устанавливаете его на адаптер:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
viewModel.getTasks().observe(this, pagedList -> {
//noinspection Convert2MethodRef
taskAdapter.submitList(pagedList); //used to be 'setList'
});
Хитрость в том, что если вы хотите сделать его параметрическим, то вам нужно заменить здесь следующее, и чтобы представление могло его наблюдать:
liveResults = new LivePagedListBuilder<>(userDao.usersByName(input) // <-- !!
Таким образом, вы должны заменить LiveData. о_О
В этом случае вы можете удалить наблюдателей из существующих LiveData, заменить их новыми LiveData и начать наблюдать за ними.
private void startListening() {
viewModel.getTasks().observe(this, pagedList -> {
//noinspection Convert2MethodRef
taskAdapter.submitList(pagedList); // used to be 'setList'
});
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
startListening();
}
@OnTextChanged(R.id.edit_text)
public void onTextChanged(Editable editable) {
String username = editable.toString();
replaceSubscription(userName);
}
private void replaceSubscription(String userName) {
viewModel.replaceSubscription(this, userName);
startListening();
}
а также
public class UserViewModel extends ViewModel {
private LiveData<PagedList<User>> liveResults;
private String userName;
private LiveData<PagedList<User>> createFilteredUsers(String userName) {
// TODO: handle if 'null' and load all data instead
return new LivePagedListBuilder<>(userDao.usersByName(userName),
new PagedList.Config.Builder() //
.setPageSize(20) //
.setPrefetchDistance(20) //
.setEnablePlaceholders(true) //
.build())
.setInitialLoadKey(0)
.build();
}
public UserViewModel(UserDao userDao, @Nullable String userName) { // null or restored, from ViewModelProviders.of(Factory)
liveResults = createFilteredUsers(userName);
}
public void replaceSubscription(LifecycleOwner lifecycleOwner, String userName) {
this.userName = userName;
liveResults.removeObservers(lifecycleOwner);
liveResults = createFilteredUsers(userName);
}
}