我在工具栏上有一个搜索视图图标,通过创建选项菜单(菜单菜单)。单击该图标将创建一个 EditText 行,供用户输入搜索输入。我有一个文本观察器()附加到编辑文本行,以便当文本添加到该行时(在文本更改可编辑之后),搜索查询方法通过搜索房间数据库的视图模型运行。
我的问题是,观察者甚至在用户输入任何查询之前就开始创建了。使用Toasts,我能够在用户按下SearchView图标时以及用户输入任何搜索查询之前,确认观察者正在运行一个空白查询“%%”。即使在afterTextChanged()中设置了观察者,也会发生这种情况。如何让ViewModel观察者仅在用户输入文本后触发?
Activity
...
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.mainactiv_menu, menu);
searchItem = menu.findItem(R.id.action_search);
menu.findItem(R.id.action_search).setVisible(false);
if (cardsAdapter != null && cardsAdapter.getItemCount() > 0) {
menu.findItem(R.id.action_search).setVisible(true);
}
SearchManager searchManager = (SearchManager) MainActivity.this.getSystemService(Context.SEARCH_SERVICE);
if (searchItem != null) {
mSearchView = (SearchView) searchItem.getActionView();
if (mSearchView != null) {
mSearchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
EditText mSearchEditText = mSearchView.findViewById(androidx.appcompat.R.id.search_src_text);
mSearchEditText.setInputType(android.text.InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
mSearchEditText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// not needed
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// not needed
}
@Override
public void afterTextChanged(Editable s) {
String queryText = "%" + s.toString() + "%";
mQuickcardViewModel.searchQuery(queryText).observe(MainActivity.this, searchCards -> {
searchList = searchCards;
if (!mSearchView.isIconified() && searchList.size() > 0) {
// do something
}
...
如何让ViewModel观察者在用户输入文本后才触发?
在观察之前,使用< code>if语句查看字符串是否为空:
@Override
public void afterTextChanged(Editable s) {
if (s.toString().length() > 0) {
// the rest of your code goes here, preferably with some modifications
}
}
我建议的其他变化包括:
>
添加一些防抖措施。给定您的搜索表达式,您似乎正在访问search chQuery()
中的数据库。如果用户快速连续键入10个字符,您将进行10次查询,这将降低性能。“去抖”表示“仅在用户暂停一段时间后进行查询”,例如500毫秒,没有任何进一步的输入。
添加智能以在需要时取消未完成的查询。假设用户键入了一点,然后反跳周期过去了。因此,您可以触发查询。由于您的(假定的)LIKE
表达式,您的查询将执行“表扫描”,检查表的每一行。这可能会很慢,并且用户可能会在第一个查询完成之前开始键入更多内容。您不再需要该查询,因为它的结果是错误的(它适用于以前的搜索表达式,而不是当前搜索表达式)。因此,您需要一种方法来取消该工作。
处理配置更改。你可能会争辩说你正在使用视图模型
和实时数据
,它们应该处理这个问题......它确实如此,但前提是您正确使用它们。在您的情况下,您似乎在观察它之后丢弃了该LiveData
,并且以此类推,配置更改,您将无法在位置上重新观察它。这就是为什么很多样本都集中在将“请做后台工作”与“请给我后台工作的结果”脱钩的原因。您仍然可以使用调用的搜索查询()
方法,但它将返回 void
。结果将通过视图模型
保存的一些实时数据
进行管道传输,您可以在 onCreate()
中观察到这些实时数据。这样,在配置更改后,您再次观察 LiveData
,并获取该配置更改之前的数据。
利用FTS。< code>LIKE比较慢。如果您经常这样做,可以考虑在SQLite中使用FTS3/FTS4进行全文搜索。如果您使用的是Room,那么在Room 2.2.0中对此有内置的支持。
是否有一种设计模式可以形成一个“复合”观察者/可观察者? 我的意思是我有一个可观察的,它在某个变化时通知它的监听器。 每个监听器也是一个可观察的,并通知它自己的监听器(在某个动作上,它做了哪个动作是由第一个可观察的通知触发的)。 这种观察者/可观察的“链接”作为设计是可以的,还是有一个标准的模式?
主要内容:介绍,实现,Subject.java,Observer.java,BinaryObserver.java,OctalObserver.java,HexaObserver.java,ObserverPatternDemo.java当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。 介绍 意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知
观察者模式 亦称: 事件订阅者、监听者、Event-Subscriber、Listener、Observer 意图 观察者模式是一种行为设计模式, 允许你定义一种订阅机制, 可在对象事件发生时通知多个 “观察” 该对象的其他对象。 问题 假如你有两种类型的对象: 顾客和 商店 。 顾客对某个特定品牌的产品非常感兴趣 (例如最新型号的 iPhone 手机), 而该产品很快将会在商店里出售。 顾客
一、定义 观察者模式(发布-订阅模式):其定义对象间一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。 在JavaScript中,一般使用事件模型来替代传统的观察者模式。 好处: (1)可广泛应用于异步编程中,是一种替代传递回调函数的方案。 (2)可取代对象之间硬编码的通知机制,一个对象不用再显示地调用另外一个对象的某个接口。两对象轻松解耦。 二、DOM事件–观察者
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。 介绍 意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。 主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。 何时使用:一个对象(目标对象)
观察者模式是软件设计模式的一种。在此种模式中,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实时事件处理系统。 定义一个目标构造函数,并实现绑定、解绑和触发等方法: function Subject() { this.events = {}; this.count = 0; } Subj