Android MultiAutoCompleteTextView和Firebase

Android MultiAutoCompleteTextView和Firebase,android,firebase,firebase-realtime-database,multiautocompletetextview,Android,Firebase,Firebase Realtime Database,Multiautocompletetextview,我有一个存储在Firebase中的标签列表。在我的一个片段中,一个MultiAutoCompleteTextView(MACTV)允许用户选择相关的标签 目标, 是使用 来自Firebase的标签 一旦用户使用从MACTV选择相关标签 在McClickListener中,所选标记需要保存到 火基 下面是我如何尝试实现的 定义MACTV的阵列适配器: MACTV的代码 将所选标记保存到Firebase List ArticleTags=newarraylist(Arrays.asList(Ar

我有一个存储在Firebase中的标签列表。在我的一个片段中,一个MultiAutoCompleteTextView(MACTV)允许用户选择相关的标签

目标,

  • 是使用 来自Firebase的标签
  • 一旦用户使用从MACTV选择相关标签 在McClickListener中,所选标记需要保存到 火基
下面是我如何尝试实现的

定义MACTV的阵列适配器:

MACTV的代码

将所选标记保存到Firebase

List ArticleTags=newarraylist(Arrays.asList(ArticleTags.getText().toString().split(“,”));
DatabaseReference db=FirebaseDatabase.getInstance().getReference().child(“标记”).setValue(ArticleTags);
阈值定义为2。不幸的是,当我开始在MACTV中输入时,没有相关的标签显示为弹出窗口


我哪里出错了?

顺便说一句,好问题!这是我这个月见过的最有趣的一次

首先,使用此代码可以将整个
标记
节点加载到设备。想象一下,您有2M个标记(是否有?),这段代码还能工作吗?;)

第二件事是在工作线程上调用
onDataChange
中的代码(以及所有firebase回调中的代码),但应在UI线程中调用适配器方法

最后,以下是我对解决方案的看法:

  • 您需要使用查询(您可以在中阅读更多)
  • 首先,我们需要按名称对标记进行排序。这就是基本查询:

    DatabaseReference baseRef = FirebaseDatabase.getInstance().getReference().child("tags").orderByChild("tagName");
    
  • 下一步-您必须使用以下代码将
    TextWatcher
    附加到您的
    MultiAutoCompleteTextView

    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) {}
    
    });
    
    articleTags.addTextChangedListener(新的TextWatcher(){
    @重写PreforeTextChanged之前的公共void(CharSequence CharSequence,int i,int i1,int i2){}
    @凌驾
    public void onTextChanged(CharSequence CharSequence,int i,int i1,int i2){
    
    if(charSequence.length)在向adapter.adapterMultiAutoComplete.notifyDataSetChanged()添加项后,只需在onDataChange()方法中添加此行;相关(不重复)问答感谢您为解决方案引入了另一种视角。我之前没有想过使用查询。但哪种方式更好?案例01:使用for循环获取所有可用的标记名。在这种情况下,上行搜索速度更快,但在涉及太多标记时没有意义。案例02:(使用查询),涉及的搜索时间太长(例如,当我希望搜索并添加十个标记时)@user3314337将limit设置为100,例如。如果得到的值少于100,请将它们保存在适配器中,并且不要进行更多查询=)
    MultiAutoCompleteTextView articleTags = (MultiAutoCompleteTextView) findViewById(R.id.mactv_tags);
    articleTags.requestFocus();
    articleTags.setTokenizer(new MultiAutoCompleteTextView.CommaTokenizer());
    articleTags.setAdapter(adapterMultiAutoComplete);
    
    List<String> ArticleTags = new ArrayList<>(Arrays.asList(articleTags.getText().toString().split(", ")));
    DatabaseReference db = FirebaseDatabase.getInstance().getReference().child("tags").setValue(ArticleTags);
    
    DatabaseReference baseRef = FirebaseDatabase.getInstance().getReference().child("tags").orderByChild("tagName");
    
    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) {}
    
    });