在单独的线程中从服务中获取 AutoCompleteTextView 建议 [英] Fetch AutoCompleteTextView suggestions from service in separate thread

查看:23
本文介绍了在单独的线程中从服务中获取 AutoCompleteTextView 建议的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于我的 AutoCompleteTextView,我需要从网络服务中获取数据.因为这可能需要一点时间,我不希望 UI 线程没有响应,所以我需要以某种方式在单独的线程中获取数据.例如,当从 SQLite DB 获取数据时,使用 CursorAdapter 方法 - runQueryOnBackgroundThread 很容易完成.我正在寻找其他适配器,例如 ArrayAdapterBaseAdapter,但找不到任何类似的东西...

For my AutoCompleteTextView I need to fetch the data from a webservice. As it can take a little time I do not want UI thread to be not responsive, so I need somehow to fetch the data in a separate thread. For example, while fetching data from SQLite DB, it is very easy done with CursorAdapter method - runQueryOnBackgroundThread. I was looking around to other adapters like ArrayAdapter, BaseAdapter, but could not find anything similar...

有没有一种简单的方法可以实现这一目标?我不能简单地直接使用 ArrayAdapter,因为建议列表是动态的 - 我总是根据用户输入获取建议列表,因此无法预取和缓存以供进一步使用...

Is there an easy way how to achieve this? I cannot simply use ArrayAdapter directly, as the suggestions list is dynamic - I always fetch the suggestions list depending on user input, so it cannot be pre-fetched and cached for further use...

如果有人可以就这个主题提供一些提示或示例 - 那就太好了!

If someone could give some tips or examples on this topic - would be great!

推荐答案

通过上述方法,我在打字速度非常快时也遇到了这些问题.我猜是因为过滤器类对结果的过滤是异步完成的,所以在过滤完成的同时在ui线程中修改Adapter的ArrayList可能会出现问题.

With the approach above, i also had those problems when typing very fast. I guess it´s because the filtering of the results is done asynchronously by the filter class, so there can be problems when modifying the ArrayList of the Adapter in the ui thread while filtering is done.

http://developer.android.com/reference/android/widget/Filter.html

但是使用以下方法一切正常.

However with following approach everything worked fine.

public class MyActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        MyAdapter myAdapter = new MyAdapter(this, android.R.layout.simple_dropdown_item_1line);

        AutoCompleteTextView acTextView = (AutoCompleteTextView) findViewById(R.id.autoCompleteTextView1);
        acTextView.setAdapter(myAdapter);
    }
}

public class MyAdapter extends ArrayAdapter<MyObject> {
    private Filter mFilter;

    private List<MyObject> mSubData = new ArrayList<MyObject>();
    static int counter=0;

    public MyAdapter(Context context, int textViewResourceId) {
      super(context, textViewResourceId);
      setNotifyOnChange(false);

      mFilter = new Filter() {
        private int c = ++counter;
        private List<MyObject> mData = new ArrayList<MyObject>();

        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
          // This method is called in a worker thread
          mData.clear();

          FilterResults filterResults = new FilterResults();
          if(constraint != null) {
            try {
              // Here is the method (synchronous) that fetches the data
              // from the server      
              URL url = new URL("...");
              URLConnection conn = url.openConnection();
              BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
              String line = "";

              while ((line = rd.readLine()) != null) {
                      mData.add(new MyObject(line));
              }
            }
            catch(Exception e) {
            }

            filterResults.values = mData;
            filterResults.count = mData.size();
          }
          return filterResults;
        }

        @SuppressWarnings("unchecked")
        @Override
        protected void publishResults(CharSequence contraint, FilterResults results) {
          if(c == counter) {
            mSubData.clear();
              if(results != null && results.count > 0) {
                ArrayList<MyObject> objects = (ArrayList<MyObject>)results.values;
                for (MyObject v : objects)
                  mSubData.add(v);

                notifyDataSetChanged();
              }
              else {
                notifyDataSetInvalidated();
              }
          }
        }
    };
  }

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

  @Override
  public MyObject getItem(int index) {
    return mSubData.get(index);
  }

  @Override
  public Filter getFilter() {
    return mFilter;
  }
}

这篇关于在单独的线程中从服务中获取 AutoCompleteTextView 建议的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆