使用android Paging库,从块中加载数据库中的数据真的很容易,ViewModel提供了自动UI更新和数据保留。所有这些框架模块都可以帮助我们在android平台上创建出色的应用。
[典型的android应用必须显示项目列表,并允许用户搜索该列表。这就是我想通过我的应用程序实现的目标。因此,我通过阅读许多文档,教程甚至stackoverflow答案来完成实现。 但是我不确定我是正确执行还是应该执行该操作。因此,在下面,我展示了使用ViewModel和RecyclerView实现分页库的方式。
[请检查我的实现并纠正我的错误之处,或者告诉我应该怎么做。我认为有很多像我这样的新android开发人员仍对如何正确执行感到困惑,因为没有单一来源可以回答您有关此类实现的所有问题。
我只展示我认为重要的内容。我正在使用Room。这是我正在使用的实体。
@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);
}
这里是ViewModel扩展了AndroidViewModel,它允许通过根据搜索文本提供所有事件或已过滤事件的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;
}
对于搜索事件,我正在使用SearchView。在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;
}
我将强烈建议您开始使用RxJava,它可以简化整个搜索逻辑的问题。
我建议在Dao Room Class中实现两种方法,一种是在搜索为空时查询所有数据,另一种是按照以下方式查询搜索到的项目。数据源用于在页面列表中加载数据
@Query("SELECT * FROM food order by food_name")
DataSource.Factory<Integer, Food> loadAllFood();
@Query("SELECT * FROM food where food_name LIKE :name order by food_name")
DataSource.Factory<Integer, Food> loadAllFoodFromSearch(String name);
在ViewModel类中,我们需要两个参数,其中一个将用于观察搜索到的文本,而我们使用MutableLiveData来在OnChange期间通知视图。然后LiveData观察Items列表并更新UI。SwitchMap应用接受输入LiveData并生成相应LiveData输出的功能。请找到下面的代码
public LiveData<PagedList<Food>> listAllFood;
public MutableLiveData<String> filterFoodName = new MutableLiveData<>();
public void initialFood(final FoodDao foodDao) {
this.foodDao = foodDao;
PagedList.Config config = (new PagedList.Config.Builder())
.setPageSize(10)
.build();
listAllFood = Transformations.switchMap(filterFoodName, outputLive -> {
if (outputLive == null || outputLive.equals("") || input.equals("%%")) {
//check if the current value is empty load all data else search
return new LivePagedListBuilder<>(
foodDao.loadAllFood(), config)
.build();
} else {
return new LivePagedListBuilder<>(
foodDao.loadAllFoodFromSearch(input),config)
.build();
}
});
}
viewModel然后将LiveData传播到视图,并观察数据的变化。然后在MainActivity中调用将使用SwitchMap函数的initialFood方法。
viewModel = ViewModelProviders.of(this).get(FoodViewModel.class);
viewModel.initialFood(FoodDatabase.getINSTANCE(this).foodDao());
viewModel.listAllFood.observe(this, foodlistPaging -> {
try {
Log.d(LOG_TAG, "list of all page number " + foodlistPaging.size());
foodsactivity = foodlistPaging;
adapter.submitList(foodlistPaging);
} catch (Exception e) {
}
});
recyclerView.setAdapter(adapter);
对于第一个onCreate,将filterFoodName初始化为Null,以便检索所有项目。viewModel.filterFoodName.setValue(“”);
然后将TextChangeListener应用于EditText并调用MutableLiveData,它将观察更改并使用搜索到的Item更新UI。
searchFood.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i,
int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int
i1, int i2) {
}
@Override
public void afterTextChanged(Editable editable) {
//just set the current value to search.
viewModel.filterFoodName.
setValue("%" + editable.toString() + "%");
}
});
}
下面是我的完整代码的github回购。
https://github.com/muchbeer/PagingSearchFood
希望有帮助
显然,你是对的。使用前先了解MVVM
时。这里是图像和source
当然,您可以使用'androidx.lifecycle:lifecycle-extensions:2.0.0'方便地创建视图模型。