我正在开发依赖SQLite数据库的应用程序来填充autoCompleteTextView
,因此当用户输入一些文本时,应用会根据用户输入显示建议列表。
我想提供下一步并实施一个简单的Firebase数据库来存储autoCompleteTextview
所需的单词列表。由于我在使用Firebase时相当新,因此无法从Firebase数据库中获取de数据。
我真的不知道如何开始,我认为我应该创建一个自定义的ArrayAdapter并重写其方法,以便每次在AutocompleteTextView
中更改文本时动态搜索数据库
或者搜索数据库中的所有单词并将它们放在一个ArrayList
中,以便与TextView.
希望收到你的来信,并感谢你们。
答案 0 :(得分:0)
我通过创建自定义ArrayAdapter
来监听Firestore查询并实现Filterable
,从而使用Firestore做类似的事情。
public class ProductAdapter extends ArrayAdapter<Product>
implements Filterable, EventListener<QuerySnapshot> {
private final Object mLock = new Object();
private static final java.lang.String TAG = "Product Adapter";
private ArrayList<Product> mProducts = new ArrayList<>();
private ArrayList<Product> mOriginalValues;
private ArrayFilter mFilter;
private CharSequence mFilterPrefix;
private Query mQuery;
private ListenerRegistration mRegistration;
public ProductAdapter(Context context, int resource, Query query) {
super(context, resource);
mQuery = query;
}
@Override
public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e) {
if (e != null) {
Log.w(TAG, "onEvent:error", e);
return;
}
for (DocumentChange change : documentSnapshots.getDocumentChanges()) {
switch (change.getType()) {
case ADDED:
onDocumentAdded(change);
break;
case MODIFIED:
onDocumentModified(change);
break;
case REMOVED:
onDocumentRemoved(change);
break;
}
if (mFilterPrefix != null) {
getFilter().filter(mFilterPrefix);
}
}
}
public void startListening() {
if (mQuery != null && mRegistration == null) {
mRegistration = mQuery.addSnapshotListener(this);
}
}
public void stopListening() {
if (mRegistration != null) {
mRegistration.remove();
mRegistration = null;
}
synchronized (mLock) {
if (mOriginalValues != null) {
mOriginalValues.clear();
} else {
mProducts.clear();
}
}
notifyDataSetChanged();
}
public void setQuery(Query query) {
stopListening();
synchronized (mLock) {
if (mOriginalValues != null) {
mOriginalValues.clear();
}
mProducts.clear();
}
notifyDataSetChanged();
mQuery = query;
startListening();
}
protected void onDocumentAdded(DocumentChange change) {
synchronized (mLock) {
if (mOriginalValues != null) {
mOriginalValues.add(change.getNewIndex(), change.getDocument().toObject(Product.class));
} else {
mProducts.add(change.getNewIndex(), change.getDocument().toObject(Product.class));
}
}
notifyDataSetChanged();
}
protected void onDocumentModified(DocumentChange change) {
synchronized (mLock) {
if (change.getOldIndex() == change.getNewIndex()) {
if (mOriginalValues != null) {
mOriginalValues.set(change.getOldIndex(), change.getDocument().toObject(Product.class));
} else {
mProducts.set(change.getOldIndex(), change.getDocument().toObject(Product.class));
}
} else {
if (mOriginalValues != null) {
mOriginalValues.remove(change.getOldIndex());
mOriginalValues.add(change.getNewIndex(), change.getDocument().toObject(Product.class));
} else {
mProducts.remove(change.getOldIndex());
mProducts.add(change.getNewIndex(), change.getDocument().toObject(Product.class));
}
}
}
notifyDataSetChanged();
}
protected void onDocumentRemoved(DocumentChange change) {
synchronized (mLock) {
if (mOriginalValues != null) {
mOriginalValues.remove(change.getOldIndex());
} else {
mProducts.remove(change.getOldIndex());
}
}
notifyDataSetChanged();
}
@Override
public int getCount() {
return mProducts.size();
}
@Override
public Product getItem(int position){
return mProducts.get(position);
}
@Override
public long getItemId(int position){
return position;
}
@Override
public View getView(int position, final View convertView, final ViewGroup parent) {
TextView label = (TextView) super.getView(position, convertView, parent);
label.setText(mProducts.get(position).getName());
return label;
}
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
TextView label = (TextView) super.getDropDownView(position, convertView, parent);
label.setText(mProducts.get(position).getName());
return label;
}
@Override
public @NonNull Filter getFilter() {
if (mFilter == null) {
mFilter = new ArrayFilter();
}
return mFilter;
}
private class ArrayFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence prefix) {
final FilterResults results = new FilterResults();
mFilterPrefix = prefix;
if (mOriginalValues == null) {
synchronized (mLock) {
mOriginalValues = new ArrayList<>(mProducts);
}
}
final ArrayList<Product> values;
synchronized (mLock) {
values = new ArrayList<>(mOriginalValues);
}
if (prefix == null || prefix.length() == 0) {
results.values = values;
results.count = values.size();
} else {
final String prefixString = prefix.toString().toLowerCase();
final int count = values.size();
final ArrayList<Product> newValues = new ArrayList<>();
for (int i = 0; i < count; i++) {
final Product product = values.get(i);
final String valueText = product.getName().toLowerCase();
if (valueText.startsWith(prefixString)) {
newValues.add(product);
} else {
final String[] words = valueText.split(" ");
if (words.length > 1) {
if (words[words.length - 1].startsWith(prefixString)) {
newValues.add(product);
} else {
for (int j = words.length - 2; j > 0; j--) {
words[j] = words[j] + " " + words[j + 1];
if (words[j].startsWith(prefixString)) {
newValues.add(product);
break;
}
}
}
}
}
}
results.values = newValues;
results.count = newValues.size();
}
return results;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
mProducts = (ArrayList<Product>) results.values;
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
}
}
然后我将此适配器设置为我的AutoCompleteTextView
的适配器。就我而言,我正在按Product
中显示的名称过滤类AutoCompleteTextView
的对象列表,但是您可以将其更改为字符串。
为清楚起见,此方法侦听查询的整个文档列表(在我的情况下为产品),然后在本地进行过滤,而不是根据AutoCompleteTextView
中键入的文本进行查询。这样,您无需在每次输入新字母时都进行查询,并且如果Firestore数据库发生更改,列表也会自动更新。如果您希望每次文本更改时都进行一次新查询,则可以尝试使用类似this的方法。
答案 1 :(得分:0)
并非完全用于自动完成,而是在recyclerview中搜索和过滤项目,我使用了这种方法。
@Override
public boolean onQueryTextChange(String s) {
Query search_query = productRef.orderBy("productName", Query.Direction.ASCENDING).startAt(s).endAt(s + "\uf8ff");
FirestoreRecyclerOptions<Product> options = new FirestoreRecyclerOptions.Builder<Product>().setQuery(search_query, Product.class).build();
productAdapter = new ProductAdapter(options);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(Product_List.this));
recyclerView.setAdapter(productAdapter);
productAdapter.startListening();
return false;
}