【问题标题】:Android: AutoCompleteTextView and Filter - Typing Delay - Why?Android:AutoCompleteTextView 和过滤器 - 键入延迟 - 为什么?
【发布时间】:2014-03-26 11:34:22
【问题描述】:

好吧,伙计们,这让我发疯了,我在互联网上找不到解决方案!
我做了一个新的 Eclipse 项目并将这段代码粘贴到里面:

https://developers.google.com/places/training/autocomplete-android

它可以工作,但是如果我输入或删除(一个)字符,则在键入它们时通常会出现延迟(短暂冻结),并且建议下拉菜单会消失并再次出现。
至于我的理解,过滤本身是异步完成的,因此来自后台线程,那么为什么短暂冻结?

我的目标是在 Google Play 商店中拥有一个无冻结的 AutoCompleteTextView。
那么你们有什么建议/解决方法来实现这一点吗?

【问题讨论】:

    标签: java android android-arrayadapter autocompletetextview android-filterable


    【解决方案1】:

    您必须使用以下库文件。您必须在 AutoCompletetextView 上调用 addTextChangeListener(Listener)。在afterTextChanged(Editable s) 里面你必须提到你需要做的功能。

    /*
     * Copyright (C) 2006 The Android Open Source Project
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package android.text;
    
    /**
     * When an object of a type is attached to an Editable, its methods will
     * be called when the text is changed.
     */
    public interface TextWatcher extends NoCopySpan {
        /**
         * This method is called to notify you that, within <code>s</code>,
         * the <code>count</code> characters beginning at <code>start</code>
         * are about to be replaced by new text with length <code>after</code>.
         * It is an error to attempt to make changes to <code>s</code> from
         * this callback.
         */
        public void beforeTextChanged(CharSequence s, int start,
                                      int count, int after);
        /**
         * This method is called to notify you that, within <code>s</code>,
         * the <code>count</code> characters beginning at <code>start</code>
         * have just replaced old text that had length <code>before</code>.
         * It is an error to attempt to make changes to <code>s</code> from
         * this callback.
         */
        public void onTextChanged(CharSequence s, int start, int before, int count);
    
        /**
         * This method is called to notify you that, somewhere within
         * <code>s</code>, the text has been changed.
         * It is legitimate to make further changes to <code>s</code> from
         * this callback, but be careful not to get yourself into an infinite
         * loop, because any changes you make will cause this method to be
         * called again recursively.
         * (You are not told where the change took place because other
         * afterTextChanged() methods may already have made other changes
         * and invalidated the offsets.  But if you need to know here,
         * you can use {@link Spannable#setSpan} in {@link #onTextChanged}
         * to mark your place and then look up from here where the span
         * ended up.
         */
        public void afterTextChanged(Editable s);
    }
    

    【讨论】:

    • 如果它解决了您的问题。对我的回答进行投票。它鼓励所有人回答你。
    • 谢谢 raguM.tech。我已经尝试过的内容:我将 Google Places 请求包装在 AsyncTask 中并在 afterTextChanged 中调用它,这可行,但是对于我键入的每个字符,下拉列表都会消失并再次出现(我怎样才能避免这种情况,所以下拉列表保持打开状态?)后来我读到,AutoCompleteTextView 已经自动连接到 TextWatcher 并且不需要添加它并使用 Filter 代替。现在我有点失去了使用什么方法。有什么想法吗?
    【解决方案2】:

    我通过放置这些代码行解决了这个问题(参见 cmets):

                @Override
                protected FilterResults performFiltering(CharSequence constraint)
                {
                    FilterResults filterResults = new FilterResults();
    
                    // ADDED CODE: TO FIX ERROR "The content of the adapter has changed but ListView did not receive a notification":
                    ArrayList <String> resultListTemp = new ArrayList <String> ();
    
                    if (constraint != null)
                    {
                        // ADDED CODE: TO STOP TYPING DELAY & TO FIX ERROR: "The content of adapter has changed but ListView did not receive a notification"
                        if (conn != null)
                        {
                            conn.disconnect();
                        }
    
                        // CHANGED CODE: TO FIX ERROR "The content of the adapter has changed but ListView did not receive a notification":
                        resultListTemp.addAll(autocomplete(constraint.toString()));
    
                        filterResults.values = resultListTemp;
                        filterResults.count = resultListTemp.size();
                    }
                    return filterResults;
                }
    
    
                @Override
                protected void publishResults(CharSequence constraint, FilterResults results)
                {
                    // ADDED CODE: TO FIX ERROR "The content of the adapter has changed but ListView did not receive a notification":
                    resultList = (ArrayList <String>) results.values;
    
                    if (results != null && results.count > 0)
                    {
                        notifyDataSetChanged();
                    }
                    else
                    {
                        notifyDataSetInvalidated();
                    }
                }
    
    
                private ArrayList<String> autocomplete(String input)
                {
                    // CHANGED CODE: TO FIX ERROR "The content of the adapter has changed but ListView did not receive a notification":
                    ArrayList<String> resultList = new ArrayList <String> ();
                    .....
                    .....
                }
    



    其中“conn”是用于获取 Google Places 数据的 HttpURLConnection。

    【讨论】:

    • 谢谢!这加上在 performFiltering 中添加一个临时的“resultListTemp”也将处理错误消息:“适配器的内容已更改,但 ListView 未收到通知”。我认为 Google Places Autocomplete Training 应该更新这些内容。
    • 您提到了 adapter.NotifydataSetChange()。如果不使用此函数在 ListView 中进行更改。然后只有列表视图不更新。
    • @raguM.tech:是的。 notifyDataSetChanged() 已经包含在 Google Places Training 示例中。
    • 如果我使用 volley 而不是 HttpURLConnection 怎么办?
    猜你喜欢
    • 1970-01-01
    • 2021-10-26
    • 1970-01-01
    • 2015-12-12
    • 2017-10-07
    • 2011-08-23
    • 2020-08-17
    • 2018-09-03
    • 2014-05-08
    相关资源
    最近更新 更多