对于我的AutoCompleteTextView
,我需要从网络服务中获取数据。因为它可能需要一点时间我不希望UI线程没有响应,所以我需要以某种方式在单独的线程中获取数据。例如,在从SQLite DB获取数据时,使用CursorAdapter
方法 - runQueryOnBackgroundThread
非常容易。我正在寻找其他适配器,例如ArrayAdapter
,BaseAdapter
,但找不到类似的东西......
有一种简单的方法可以实现这一目标吗?我不能直接使用ArrayAdapter
,因为建议列表是动态的 - 我总是根据用户输入获取建议列表,因此无法预取和缓存以供进一步使用...
如果有人可以就这个主题提供一些提示或示例 - 会很棒!
答案 0 :(得分:10)
通过上述方法,我在输入速度非常快时也遇到了这些问题。我想这是因为结果的过滤是由过滤器类异步完成的,所以在完成过滤时在ui线程中修改Adapter的ArrayList时会出现问题。
http://developer.android.com/reference/android/widget/Filter.html
然而,采用以下方法,一切正常。
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;
}
}
答案 1 :(得分:9)
已编辑:添加天真的方法以避免在您点击建议时显示下拉列表。
我在我的应用中做了类似的事情:
private AutoCompleteTextView mSearchbar;
private ArrayAdapter<String> mAutoCompleteAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
mAutoCompleteAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line);
mSearchbar = (AutoCompleteTextView) findViewById(R.id.searchbar);
mSearchbar.setThreshold(3);
mSearchbar.setAdapter(mAutoCompleteAdapter);
mSearchbar.addTextChangedListener(new TextWatcher() {
private boolean shouldAutoComplete = true;
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
shouldAutoComplete = true;
for (int position = 0; position < mAutoCompleteAdapter.getCount(); position++) {
if (mAutoCompleteAdapter.getItem(position).equalsIgnoreCase(s.toString())) {
shouldAutoComplete = false;
break;
}
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void afterTextChanged(Editable s) {
if (shouldAutoComplete) {
new DoAutoCompleteSearch().execute(s.toString());
}
}
}
}
private class DoAutoCompleteSearch extends AsyncTask<String, Void, ArrayList<String>> {
@Override
protected ArrayList<String> doInBackground(String... params) {
ArrayList<String> autoComplete = new ArrayList<String>();
//do autocomplete search and stuff.
return autoComplete;
}
@Override
protected void onPostExecute(ArrayList<String> result) {
mAutoCompleteAdapter.clear();
for (String s : result)
mAutoCompleteAdapter.add(s);
}
}
答案 2 :(得分:1)
有相同的解决方案,除了问题是一切都很好(变量在我调试时更新)但自动完成填充奇怪,如
当我键入sco时,它有结果但不显示在列表中 但是当我退格时它会显示sco的结果。在调试中,所有变量都会更新,这只会告诉我没有为AutoCompleteTextView更新UI。当我退格时它被触发更新,然后它显示早期的计算机列表然后它(同时它用新的搜索字符串的新列表项更新它。 有人遇到过这个问题吗?