gpt4 book ai didi

android - 如何让 ViewModel 观察者最初不观察?

转载 作者:行者123 更新时间:2023-11-29 16:28:34 25 4
gpt4 key购买 nike

我通过 onCreateOptionsMenu(菜单菜单)在工具栏上有一个 SearchView 图标。单击该图标会创建一个 EditText 行,供用户输入搜索内容。我有一个 TextWatcher() 附加到 EditText 行,这样当文本添加到该行时(afterTextChanged Editable s),通过搜索 Room 数据库的 ViewModel 运行 searchQuery 方法。

我的问题是观察者甚至在用户输入任何查询之前就在创建时触发。使用 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
}

...

最佳答案

How do I get the ViewModel observer to only fire after text is entered by the user?

在观察之前使用if语句判断字符串是否为空:

@Override
public void afterTextChanged(Editable s) {
if (s.toString().length() > 0) {
// the rest of your code goes here, preferably with some modifications
}
}

我建议的其他更改包括:

  • 添加一些“去抖动”措施。鉴于您的搜索表达式,您似乎在 searchQuery() 中访问数据库。如果用户快速连续键入 10 个字符,您将进行 10 次查询,这会使性能变差。 “Debounce”表示“仅在用户暂停一段时间后查询”,例如 500 毫秒,没有任何进一步的输入。

  • 添加智能以在需要时取消未完成的查询。假设用户键入了一点,然后去抖周期结束。所以,你触发了一个查询。由于您的(假定的)LIKE 表达式,您的查询将执行“表扫描”,检查表的每一行。这可能会很慢,并且用户可能会在第一个查询完成之前开始输入更多内容。您不再需要该查询,因为它的结果是错误的(它是针对先前的搜索表达式,而不是当前的)。因此,您需要一种方法来取消该工作。

  • 处理配置更改。您可能会争辩说您正在使用 ViewModelLiveData,它们应该可以处理这些问题……它确实可以处理,但前提是您正确使用它们。在您的情况下,您似乎在观察 LiveData 之后丢弃了它,等等配置更改,您将无法重新观察它。这就是为什么很多样本都专注于将“请做后台工作”与“请给我后台工作的结果”分离。您仍然可以调用 searchQuery() 方法,但它会返回 void。结果将通过 ViewModel 持有的一些 LiveData 进行传输,您在 onCreate() 中观察到这一点。这样,在配置更改后,您将再次观察到 LiveData,并获得配置更改之前的数据。

  • 使用 FTS。 LIKE 很慢。如果您打算经常这样做,请考虑在 SQLite 中使用 FTS3/FTS4 进行全文搜索。如果您使用的是 Room,Room 2.2.0 中内置了对此的支持。

关于android - 如何让 ViewModel 观察者最初不观察?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58513291/

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