分页库过滤器/搜索 [英] Paging Library Filter/Search

查看:89
本文介绍了分页库过滤器/搜索的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用如下所述的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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆