【问题标题】:Getting the data from web API in AutoCompleteTextView with custom Adapter使用自定义适配器从 AutoCompleteTextView 中的 Web API 获取数据
【发布时间】:2016-09-11 18:47:15
【问题描述】:

我已经设法创建了一个custom adapter 并从web API 读取数据,但建议未显示在下拉列表中。我按照教程在

http://makovkastar.github.io/blog/2014/04/12/android-autocompletetextview-with-suggestions-from-a-web-service/

这是我的自定义AutoCompleteTextView

public class AutoCompleteDelay extends AutoCompleteTextView {

    private static final int MESSAGE_TEXT_CHANGED = 100;
    private static final int DEFAULT_AUTOCOMPLETE_DELAY = 750;

    private int mAutoCompleteDelay = DEFAULT_AUTOCOMPLETE_DELAY;
    private ProgressBar mLoadingIndicator;

    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            AutoCompleteDelay.super.performFiltering((CharSequence) msg.obj, msg.arg1);
        }
    };

    public AutoCompleteDelay(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setLoadingIndicator(ProgressBar progressBar) {
        mLoadingIndicator = progressBar;
    }

    public void setAutoCompleteDelay(int autoCompleteDelay) {
        mAutoCompleteDelay = autoCompleteDelay;
    }

    @Override
    protected void performFiltering(CharSequence text, int keyCode) {
        if (mLoadingIndicator != null) {
            mLoadingIndicator.setVisibility(View.VISIBLE);
        }
        mHandler.removeMessages(MESSAGE_TEXT_CHANGED);
        mHandler.sendMessageDelayed(mHandler.obtainMessage(MESSAGE_TEXT_CHANGED, text), mAutoCompleteDelay);
    }

    @Override
    public void onFilterComplete(int count) {
        if (mLoadingIndicator != null) {
            mLoadingIndicator.setVisibility(View.GONE);
        }
        super.onFilterComplete(count);
    }
}

这是我的自定义Adapter

public class SearchAdapter extends BaseAdapter implements Filterable {

    private static final int MAX_RESULTS = 10;
    private Context mContext;
    private List<User> resultList = new ArrayList<User>();

    public SearchAdapter(Context context) {
        mContext = context;
    }

    @Override
    public int getCount() {
        return resultList.size();
    }

    @Override
    public User getItem(int index) {
        return resultList.get(index);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            LayoutInflater inflater = (LayoutInflater) mContext
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.search_results, parent, false);
        }
        ((TextView) convertView.findViewById(R.id.user_name)).setText(getItem(position).getName());
        ((TextView) convertView.findViewById(R.id.user_phone)).setText(getItem(position).getPhone());
        return convertView;
    }

    @Override
    public Filter getFilter() {
        Filter filter = new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                FilterResults filterResults = new FilterResults();
                if (constraint != null) {
                    List<User> users = findUsers(mContext, constraint.toString());

                    // Assign the data to the FilterResults
                    filterResults.values = users;
                    filterResults.count = users.size();
                }
                return filterResults;
            }

            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                if (results != null && results.count > 0) {
                    resultList = (List<User>) results.values;
                    notifyDataSetChanged();
                } else {
                    notifyDataSetInvalidated();
                }
            }};
        return filter;
    }

    /**
     * Returns a search result for the given book title.
     */
    private List<User> findUsers(Context context, String query) {
        // GoogleBooksProtocol is a wrapper for the Google Books API
        SearchUser request = new SearchUser(context);
        return request.sendRequest(query);
    }

}

这是xmlAdapter View 的文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp"
    android:orientation="vertical">

    <TextView
        android:id="@+id/user_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Name"
        android:textSize="18dp"
        android:textIsSelectable="false"
        android:layout_marginBottom="4dp"
        android:textColor="@color/abc_background_cache_hint_selector_material_dark" />

    <TextView
        android:id="@+id/user_phone"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="0000000000"
        android:textSize="16dp"
        android:textIsSelectable="false"
        android:layout_marginBottom="4dp"
        android:textColor="@color/switch_thumb_disabled_material_dark" />

</LinearLayout>

这是我使用“AutoCompleteTextView”的xml 文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp">

    <TextView
        android:id="@+id/error_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="User already exists"
        android:visibility="gone"
        android:textStyle="bold"
        android:textColor="@color/design_textinput_error_color_light"
        android:singleLine="true"
        android:layout_marginTop="8dp"
        android:layout_marginBottom="8dp" />

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <com.example.krazz.futsaladmin.classes.AutoCompleteDelay
                android:id="@+id/query"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:imeOptions="actionNext"
                android:inputType="textAutoComplete"></com.example.krazz.futsaladmin.classes.AutoCompleteDelay>

        </android.support.design.widget.TextInputLayout>

        <ProgressBar
            android:id="@+id/pb_loading_indicator"
            style="?android:attr/progressBarStyleSmall"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:visibility="gone" />

    </RelativeLayout>

</LinearLayout>

这是返回ArrayList&lt;User&gt;的方法

public ArrayList<User> sendRequest(final String query) {

        RequestQueue requestQueue = VolleySingleton.getsInstance().getmRequestQueue();

        //mErrorText.setVisibility(View.GONE);

        String url = String.format(AppConfig.URL_SEARCH_USERS, query, AppConfig.APP_KEY, 4);
        debug.L(url);

        StringRequest strReq = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {

                try {
                    debug.L(response.toString());
                    JSONObject jObj = new JSONObject(response);
                    JSONArray jsonArray = jObj.getJSONArray("results");

                    if(jsonArray != null){
                        for(int i=0; i<jsonArray.length(); i++){
                            JSONObject currentUser = jsonArray.getJSONObject(i);

                            int id = currentUser.getInt("id");
                            String name = currentUser.getString("name");
                            String phone = currentUser.getString("phone");
                            User users = new User(id, name, phone);
                            searchArrayList.add(users);
                        }
                    }
                    else{
                        /*mErrorText.setText("Users not found.");
                        mErrorText.setVisibility(View.VISIBLE);*/
                        debug.L("users not found");
                    }
                } catch (JSONException e) {
                    /*mErrorText.setText(e.getMessage());
                    mErrorText.setVisibility(View.VISIBLE);*/
                    debug.L(e.toString());
                }

            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                /*mErrorText.setText(R.string.error_try_again);
                mErrorText.setVisibility(View.VISIBLE);*/
                debug.L(error.toString());
            }
        });

        requestQueue.add(strReq);
        return searchArrayList;
    }

最后这里是我使用AutoCompleteTextView的地方

mQueryInputView = (AutoCompleteDelay) view.findViewById(R.id.query);
        mErrorText = (TextView) view.findViewById(R.id.error_text);

        mQueryInputView.setThreshold(THRESHOLD);
        mQueryInputView.setAdapter(new SearchAdapter(mContext));
        mQueryInputView.setLoadingIndicator((ProgressBar) view.findViewById(R.id.pb_loading_indicator));
        mQueryInputView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
                User book = (User) adapterView.getItemAtPosition(position);
                mQueryInputView.setText(book.getPhone());
            }
        });

没有错误或任何东西,但即使API 返回值,我的下拉建议列表也没有显示。我做错了什么?

【问题讨论】:

标签: android api autocompletetextview


【解决方案1】:

问题是你返回的是一个空的 ArrayList !!!

当您向 Volley Que 添加请求时,它会在另一个线程中完成您的请求,并在服务器响应时向您返回数据。所以这需要时间。 但是在将请求添加到 Que 之后,您会返回数组列表

 requestQueue.add(strReq);
 return searchArrayList;

你应该做的是:

  if(jsonArray != null){
       for(int i=0; i<jsonArray.length(); i++){
            ...
            searchArrayList.add(users);
       }
   // RENEW YOUR ADAPTER HERE OR ASSIGN IT AGAIN TO THE EDITTEXT
    mAdapter.notifydataSetChanged();
   }

还可以尝试更改 SearchAdapter 的构造函数。一旦我遇到片段适配器的类似问题:

private List<User> resultList = new ArrayList<User>();

public SearchAdapter(Context context,List<User> data) {
    mContext = context;
    resultList = data;
}

【讨论】:

  • 好的,我在收到来自服务器的响应后添加了searchAdapter.updateAdapter(searchArrayList);。在updateAdapter() 我有searchArrayList = arraylist; this.notifyDataSetChanged();。但仍然没有显示下拉列表。请帮我解决这个问题。
  • 试试 searchAdapter.updateAdapter(searchArrayList);在 runOnUiThread 中。也许这可以解决问题。同样在你的 updateAdapter 函数中,你应该有这个 'resultList = searchArrayList' ! @LalitThapa
  • 我按照你告诉@Smartiz 的方法做了,但仍然没有得到下拉列表。
  • 感谢@Smartiz 抽出宝贵时间,但我只使用ArrayAdapter 就让它工作了,而且我根本没有使用我的自定义适配器。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-07
  • 2023-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多