使用firebase数据库填充autoCompleteTextView

时间:2018-04-15 23:02:46

标签: android database firebase firebase-realtime-database

我正在开发依赖SQLite数据库的应用程序来填充autoCompleteTextView,因此当用户输入一些文本时,应用会根据用户输入显示建议列表。

我想提供下一步并实施一个简单的Firebase数据库来存储autoCompleteTextview所需的单词列表。由于我在使用Firebase时相当新,因此无法从Firebase数据库中获取de数据。

我真的不知道如何开始,我认为我应该创建一个自定义的ArrayAdapter并重写其方法,以便每次在AutocompleteTextView中更改文本时动态搜索数据库 或者搜索数据库中的所有单词并将它们放在一个ArrayList中,以便与TextView.

一起使用

希望收到你的来信,并感谢你们。

2 个答案:

答案 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;
            }