分页库过滤器/搜索 [英] Paging Library Filter/Search
问题描述
我正在使用如下所述的Android Paging库:
https ://developer.android.com/topic/libraries/architecture/paging.html
但是我也有一个EditText用于按名称搜索用户。 / p>
如何从分页库中过滤结果以仅显示匹配的用户?
编辑从2019年开始:坚持下去,我认为您可以通过以下方法解决此问题MediatorLiveData。
特别是 Transformations.switchMap
和其他一些魔术。
当前我正在使用
public void reloadTasks(){
if(liveResults!= null){
liveResults.removeObserver(this);
}
liveResults = getFilteredResults();
liveResults.observeForever(this);
}
但是,如果您考虑一下,您应该能够无需使用即可解决此问题( observeForever
),特别是如果我们认为 switchMap
也在做类似的事情。
因此,我们需要的是 LiveData< SelectedOption>
,将其映射到 LiveData< PagedList< T>
private MutableLiveData< String> filterText = new MutableLiveData<>();
私人最终LiveData< List< List>数据;
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(){
返回数据;
}
通过MediatorLiveData处理从一个到另一个的实际更改。如果要缓存LiveData,则可以在传递给该方法的匿名实例中进行操作。
data = Transformations .switchMap(
filterText,new Function< String,LiveData< List< List< T>>>>>>(){
private Map< String,LiveData< List< List< T>>> cachedLiveData = new HashMap< ;>();
@Override
public LiveData< List< T>> apply(String input){
// ...
}
}
原始答案(它们已过时)
编辑:实际上,尽管这对于常规 LiveData<?>
来说是合理的,但可以使用Paging来参数化Factory,然后使数据源无效并获得免费评估的新数据源。
因此,在使用分页时,另一个答案中提到的方法是更好的选择。
原始答案:
您知道如何使用这样的适配器:
公共类TaskAdapter
扩展了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)
。建立();
然后您将在ViewModel中观察页面列表并将其设置为适配器:
受保护的无效onCreate(捆绑保存的InstanceState){
super.onCreate(savedInstanceState);
...
viewModel.getTasks()。observe(this,pagedList-> {
// noinspection Convert2MethodRef
taskAdapter.submitList(pagedList); //以前是setList
});
好吧,棘手的事情是,如果要使其参数化,则必须替换
liveResults = new LivePagedListBuilder<>(userDao.usersByName(input )//<-!!
因此必须替换LiveData。o_o
在这种情况下,您可以做的是从现有LiveData中删除观察者,将其替换为新的LiveData,然后开始观察。
private void startListening(){
viewModel.getTasks()。observe(this,pagedList-> {
// noinspection Convert2MethodRef
taskAdapter .submitList(pagedList); //以前是`setList`
});
}
受保护的void onCreate(捆绑保存的InstanceState){
super.onCreate( savedInstanceState);
...
startListening();
}
@OnTextChanged(R.id.edit_text)
公共vo id onTextChanged(Editable editable){
字符串username = editable.toString();
replaceSubscription(userName);
}
private void replaceSubscription(String userName){
viewModel.replaceSubscription(this,userName);
startListening();
}
和
公共类UserViewModel扩展了ViewModel {
private LiveData< PagedList< User>> liveResults;
私有字符串userName;
private LiveData< PagedList< User>> createFilteredUsers(String userName){
// TODO:如果`null`并加载所有数据,则代替
返回新的LivePagedListBuilder<>(userDao.usersByName(userName),
新建PagedList.Config .Builder()//
.setPageSize(20)//
.setPrefetchDistance(20)//
.setEnablePlaceholders(true)//
.build())
.setInitialLoadKey(0)
.build();
}
public UserViewModel(UserDao userDao,@Nullable String userName){//为null或从ViewModelProviders.of(Factory)恢复。
liveResults = createFilteredUsers(userName);
}
public void replaceSubscription(LifecycleOwner lifecycleOwner,String userName){
this.userName = userName;
liveResults.removeObservers(lifecycleOwner);
liveResults = createFilteredUsers(userName);
}
}
I am using the Android Paging Library like described here: https://developer.android.com/topic/libraries/architecture/paging.html
But i also have an EditText for searching Users by Name.
How can i filter the results from the Paging library to display only matching Users?
EDIT from 2019: hold on, I think you might be able to solve this with a MediatorLiveData.
Specifically Transformations.switchMap
and some additional magic.
Currently I was using
public void reloadTasks() {
if(liveResults != null) {
liveResults.removeObserver(this);
}
liveResults = getFilteredResults();
liveResults.observeForever(this);
}
But if you think about it, you should be able to solve this without use of observeForever
, especially if we consider that switchMap
is also doing something similar.
So what we need is a LiveData<SelectedOption>
that is switch-mapped to the LiveData<PagedList<T>>
that we need.
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;
}
This way the actual changes from one to another are handled by a MediatorLiveData. If we want to cache the LiveDatas, then we can do in the anonymous instance that we pass to the method.
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) {
// ...
}
}
ORIGINAL ANSWERS (they are outdated)
EDIT: actually. While this makes sense for a regular LiveData<?>
, with Paging, you can actually parameterize the Factory and then invalidate the Datasource and get a new datasource evaluated for free. Without recreating the query holder itself.
So the method mentioned in the other answer is a better option when you're using Paging.
ORIGINAL ANSWER:
You know how you have the adapter like this:
public class TaskAdapter
extends PagedListAdapter<Task, TaskAdapter.ViewHolder> {
public TaskAdapter() {
super(Task.DIFF_ITEM_CALLBACK);
}
In the ViewModel you set up a live paged list and expose it:
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();
Then you observe the paged list in the ViewModel and set it to the adapter:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
viewModel.getTasks().observe(this, pagedList -> {
//noinspection Convert2MethodRef
taskAdapter.submitList(pagedList); //used to be `setList`
});
Well, the tricky thing is that if you want to make it parametric, then you have to replace the following here, and make the view be able to observe it:
liveResults = new LivePagedListBuilder<>(userDao.usersByName(input) // <-- !!
So you must replace the LiveData. o_o
What you can do in that case is remove the observers from the existing LiveData, replace it with new LiveData, and start observing it.
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();
}
and
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);
}
}
这篇关于分页库过滤器/搜索的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!