gpt4 book ai didi

android - 通过观察 ViewModel 在 RecyclerView 中搜索 PagedList 的 LiveData

转载 作者:行者123 更新时间:2023-12-03 13:27:27 31 4
gpt4 key购买 nike

使用 android Paging 库,从数据库中分 block 加载数据非常容易,ViewModel 提供自动 UI 更新和数据生存。所有这些框架模块都帮助我们在 android 平台上创建了一个很棒的应用程序。

典型的 android 应用程序必须显示项目列表并允许用户搜索该列表。这就是我想用我的应用程序实现的目标。因此,我通过阅读许多文档、教程甚至 stackoverflow 答案来完成了一个实现。 但我不太确定我是否正确地做这件事或我应该如何做。 所以下面,我展示了我用 ViewModel 和 RecyclerView 实现分页库的方法。

请检查我的实现并纠正我的错误或告诉我应该如何做。我认为有很多像我这样的新 android 开发人员仍然对如何正确地做到这一点感到困惑,因为没有单一的来源可以回答你关于这种实现的所有问题。

我只展示我认为重要的展示。我正在使用房间。这是我正在使用的实体。

@Entity(tableName = "event")
public class Event {
@PrimaryKey(autoGenerate = true)
public int id;

public String title;
}

这是事件实体的 DAO。
@Dao
public interface EventDao {
@Query("SELECT * FROM event WHERE event.title LIKE :searchTerm")
DataSource.Factory<Integer, Event> getFilteredEvent(String searchTerm);
}

这里是 查看型号 延长 AndroidViewModel 通过提供 允许阅读和搜索LiveData > 根据搜索文本选择所有事件或过滤事件。我真的很挣扎,每次当 filterEvent 发生变化时,我都会创建新的 LiveData,这可能是多余的或坏的。
private MutableLiveData<Event> filterEvent = new MutableLiveData<>();
private LiveData<PagedList<Event>> data;

private MeDB meDB;

public EventViewModel(Application application) {
super(application);
meDB = MeDB.getInstance(application);

data = Transformations.switchMap(filterEvent, new Function<Event, LiveData<PagedList<Event>>>() {
@Override
public LiveData<PagedList<Event>> apply(Event event) {
if (event == null) {
// get all the events
return new LivePagedListBuilder<>(meDB.getEventDao().getAllEvent(), 5).build();
} else {
// get events that match the title
return new LivePagedListBuilder<>(meDB.getEventDao()
.getFilteredEvent("%" + event.title + "%"), 5).build();
}
}
});
}

public LiveData<PagedList<Event>> getEvent(Event event) {
filterEvent.setValue(event);
return data;
}

对于搜索事件,我使用 搜索查看 .在 onQueryTextChange 中,我编写了以下代码来搜索或显示未提供搜索词的所有事件,这意味着搜索已完成或已取消。
Event dumpEvent;

@Override
public boolean onQueryTextChange(String newText) {

if (newText.equals("") || newText.length() == 0) {
// show all the events
viewModel.getEvent(null).observe(this, events -> adapter.submitList(events));
}

// don't create more than one object of event; reuse it every time this methods gets called
if (dumpEvent == null) {
dumpEvent = new Event(newText, "", -1, -1);
}

dumpEvent.title = newText;

// get event that match search terms
viewModel.getEvent(dumpEvent).observe(this, events -> adapter.submitList(events));

return true;
}

最佳答案

感谢 George Machibya为他的伟大answer .但我更喜欢对其进行一些修改,如下所示:

  • 在内存中保留无过滤数据以使其更快或每次加载它们以优化内存之间存在权衡。我更喜欢将它们保存在内存中,因此我将部分代码更改如下:
  • listAllFood = Transformations.switchMap(filterFoodName), input -> {
    if (input == null || input.equals("") || input.equals("%%")) {
    //check if the current value is empty load all data else search
    synchronized (this) {
    //check data is loaded before or not
    if (listAllFoodsInDb == null)
    listAllFoodsInDb = new LivePagedListBuilder<>(
    foodDao.loadAllFood(), config)
    .build();
    }
    return listAllFoodsInDb;
    } else {
    return new LivePagedListBuilder<>(
    foodDao.loadAllFoodFromSearch("%" + input + "%"), config)
    .build();
    }
    });
  • 拥有去抖动器有助于减少对数据库的查询次数并提高性能。所以我开发了DebouncedLiveData如下所示,并从 filterFoodName 制作一个去抖动的 livedata .
  • public class DebouncedLiveData<T> extends MediatorLiveData<T> {

    private LiveData<T> mSource;
    private int mDuration;
    private Runnable debounceRunnable = new Runnable() {
    @Override
    public void run() {
    DebouncedLiveData.this.postValue(mSource.getValue());
    }
    };
    private Handler handler = new Handler();

    public DebouncedLiveData(LiveData<T> source, int duration) {
    this.mSource = source;
    this.mDuration = duration;

    this.addSource(mSource, new Observer<T>() {
    @Override
    public void onChanged(T t) {
    handler.removeCallbacks(debounceRunnable);
    handler.postDelayed(debounceRunnable, mDuration);
    }
    });
    }
    }

    然后像下面这样使用它:
    listAllFood = Transformations.switchMap(new DebouncedLiveData<>(filterFoodName, 400), input -> {
    ...
    });
  • 我通常更喜欢使用 DataBiding在安卓。通过使用双向数据绑定(bind),您不需要使用 TextWatcher更多,您可以直接将 TextView 绑定(bind)到 viewModel。

  • 顺便说一句,我修改了 George Machibya 解决方案并将其推送到我的 Github 中。更多详情可以查看here .

    关于android - 通过观察 ViewModel 在 RecyclerView 中搜索 PagedList 的 LiveData,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59685220/

    31 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com