I have a list of Tags stored in Firebase. In one of my Fragments, a MultiAutoCompleteTextView (MACTV) lets the User, to select the relevant Tags.
The objective,
Here's how I tried implementing.
Defining the ArrayAdapter for MACTV:
ArrayAdapter<String> adapterMultiAutoComplete = new ArrayAdapter<>(getActivity(), android.R.layout.simple_list_item_1);
Using the AddValueEventListener to populate the ArrayAdapter
if (fbUser != null) {
dbTags.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
//Basically, this says "For each DataSnapshot *Data* in dataSnapshot, do what's inside the method.
for (DataSnapshot tagNameSnapshot : dataSnapshot.getChildren()) {
//Get the suggestion by childing the key of the string you want to get.
String ValueTagName = tagNameSnapshot.child("tagName")).getValue(String.class);
//Add ValueTagName to ArrayAdapter
adapterMultiAutoComplete.add(ValueTagName);
}
}
@Override
public void onCancelled(DatabaseError databaseError) {/*Do Nothing*/}
});
}
Code for MACTV
MultiAutoCompleteTextView articleTags = (MultiAutoCompleteTextView) findViewById(R.id.mactv_tags);
articleTags.requestFocus();
articleTags.setTokenizer(new MultiAutoCompleteTextView.CommaTokenizer());
articleTags.setAdapter(adapterMultiAutoComplete);
Saving the selected tags to Firebase
List<String> ArticleTags = new ArrayList<>(Arrays.asList(articleTags.getText().toString().split(", ")));
DatabaseReference db = FirebaseDatabase.getInstance().getReference().child("tags").setValue(ArticleTags);
The Threshold value is defined as 2. Unfortunately, no relevant tags appear as pop-up when I start typing in MACTV.
Where did I go wrong?
BTW, great question! The most interesting I've seen this month.
First of all, with this code you loading whole tags
node to device. Imagine, you have 2M of tags (does SO has?), will this code still work? ;)
The second thing, code inside onDataChange
(as well as code in all firebase callbacks) is called on worker thread, but adapter methods should be called in UI thread.
And the last, here is how I see the solution:
First of all, we need to sort tags by name. So this is base query:
DatabaseReference baseRef = FirebaseDatabase.getInstance().getReference().child("tags").orderByChild("tagName");
Next - you must attach TextWatcher
to your MultiAutoCompleteTextView
with following code
articleTags.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) {
if (charSequence.length <3) return;
String searchTarget = charSequence.toString().toLowerCase();
//Here magic happens)
baseRef.startAt(searchTarget).endAt(searchTarget + "\uf8ff").limitToFirst(20).addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
//Handle executing this code in main thread yourself, answer will be too long with it
adapterMultiAutoComplete.removeAll();
for (DataSnapshot data: dataSnapshot.getChildren()) {
adapterMultiAutoComplete.add(data.getValue(String.class))
}
adapterMultiAutoComplete.notifyDatasetChanged();
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.wtf("What a terrible failure!", databaseError.toException());
}
});
}
@Override public void afterTextChanged(Editable editable) {}
});
P.S.: Code never tested and probably not working. But you got the idea ;)