【问题标题】:MultiAutoCompleteTextView and FirebaseMultiAutoCompleteTextView 和 Firebase
【发布时间】:2017-03-10 04:43:54
【问题描述】:

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

目标,

  • 是使用 来自 Firebase 的代码。
  • 一旦用户使用 MACTV 从 MACTV 选择相关标签 OnItemClickListener,选中的Tags需要保存到 Firebase。

这是我尝试实施的方法。

为 MACTV 定义 ArrayAdapter

ArrayAdapter<String> adapterMultiAutoComplete = new ArrayAdapter<>(getActivity(), android.R.layout.simple_list_item_1);

使用 AddValueEventListener 填充 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*/}
   });
}

MACTV 代码

MultiAutoCompleteTextView articleTags = (MultiAutoCompleteTextView) findViewById(R.id.mactv_tags);
articleTags.requestFocus();
articleTags.setTokenizer(new MultiAutoCompleteTextView.CommaTokenizer());
articleTags.setAdapter(adapterMultiAutoComplete);

将选中的标签保存到 Firebase

List<String> ArticleTags = new ArrayList<>(Arrays.asList(articleTags.getText().toString().split(", ")));
DatabaseReference db = FirebaseDatabase.getInstance().getReference().child("tags").setValue(ArticleTags);

阈值定义为 2。不幸的是,当我开始输入 MACTV 时,没有相关标签显示为弹出窗口。

我哪里做错了?

【问题讨论】:

  • 在将项目添加到适配器后,只需在 onDataChange() 方法中添加这一行。 adapterMultiAutoComplete.notifyDataSetChanged();
  • 相关(非重复)问题与答案stackoverflow.com/a/39715702/5593959

标签: android firebase firebase-realtime-database multiautocompletetextview


【解决方案1】:

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

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

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

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

  1. 您需要使用查询(您可以在docs 阅读更多内容)
  2. 首先,我们需要按名称对标签进行排序。所以这是基本查询:

    DatabaseReference baseRef = FirebaseDatabase.getInstance().getReference().child("tags").orderByChild("tagName");
    
  3. 下一步 - 您必须使用以下代码将 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) {}
    
    });
    

P.S.:代码从未经过测试,可能无法正常工作。但你明白了;)

【讨论】:

  • 感谢您介绍解决方案的替代视角。我之前没想过使用查询。但哪个是更​​好的方法? 案例 01: 使用 For 循环获取所有可用的 tagNames。在这种情况下,好处是搜索速度更快,但在涉及太多标签时没有意义。在案例 02:(使用查询)中,涉及的搜索时间过多(比如当我希望搜索并添加十个标签时)
  • 例如,@user3314337 将限制设置为 100。如果您得到的值少于 100 个,请将它们保存在适配器中并且不要进行更多查询 =)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多