从单独的线程服务获取AutoCompleteTextView建议线程、建议、AutoCompleteTextView

2023-09-05 04:14:53 作者:い是我犯贱,把赔笑当溺爱

有关我的 AutoCompleteTextView 我需要从web服务获取数据。因为它可能需要一点时间,我不想UI线程不敏感,所以我需要以某种方式获取数据在单独的线程。例如,虽然从SQLite的数据库提取数据,这是很容易与的CursorAdapter done方法 - runQueryOnBackgroundThread 。我一直在寻找周围其它适配器像 ArrayAdapter BaseAdapter ,但找不到任何类似...

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 直接作为建议名单是动态的 - 我总是抓取根据用户输入的建议名单,所以它不可能是pre-取和缓存进一步使用...

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!

推荐答案

有了上面的方法,我也打字速度非常快,当有这些问题。我想it's因为结果的过滤是通过过滤器类以异步方式完成的,因此修改适配器的ArrayList中时,在UI线程同时执行过滤有可能出现问题。

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> obejcts = (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;
  }
}