这令人沮丧,我花了一周的时间试图找出如何在Android中提高自定义autocompleteTextView的性能,并且什么都没有。我甚至实现了一个Trie来保留列表项的一些索引,以便在过滤时恢复它们,但是徒劳(我想我使用它不正确或者问题出在其他地方)。我已经实现了FilterSearchTaskFragment以保持对上次启动任务的引用,并在用户在autocompleteTextView中快速键入多个字符时停止它。
在performFiltering()方法和publishResults()中,我已经设置了一些控件来恢复实际运行任务的状态(通过调用isCancelled()方法),以便尽快完成但是什么,或者更好我在ADT模拟器中测试应用程序时稍微增加了性能,但在真实设备(我的平板电脑)上似乎事情保持不变...为什么?我在弄什么?
我用Google搜索以找到一些有用的答案,但我找不到任何有同样问题的人。我甚至在这里问过SO,有人告诉我使用装载机,有人告诉我使用Handler,但是当事情发生时,没有人回复我,我也不知道如何使用它们我的情况。 我正在使用自定义的对象列表(我正在过滤一些我以前从MySQL数据库恢复的市政数据)。这是我写的所有代码:
首先是FilterSearchTaskFragment:
public class FilterSearchTaskFragment extends Fragment {
private TaskCallbacks filterSearchTaskCallbacks;
private static int taskNum;
public interface TaskCallbacks {
void onPreExecute();
void onPostExecute();
void performFilterSearch();
}
private AsyncFilterSearchAbstractTask filterSearchTask;
private boolean running;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof TaskCallbacks) {
filterSearchTaskCallbacks = (TaskCallbacks) activity;
}
else {
throw new ClassCastException(activity.toString() + " must implement the FilterSearchTaskFragment.TaskCallbacks interface!");
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
// Start the background filter search task
public void start() {
filterSearchTask = new AsyncFilterSearchAbstractTask();
filterSearchTask.execute();
taskNum++;
running = true;
}
public int getTaskNum() {
return taskNum;
}
// Cancel the execution of the background filter search task
public void cancel() {
filterSearchTask.cancel(true);
filterSearchTask = null;
running = false;
}
public boolean isRunning() {
return this.running;
}
public boolean isCancelled() {
if (filterSearchTask.isCancelled()) {
return true;
}
return false;
}
// Background filter search
private class AsyncFilterSearchAbstractTask extends AsyncTask<Void, Void, Void> {
@Override
protected void onPreExecute() {
filterSearchTaskCallbacks.onPreExecute();
running = true;
}
@Override
protected Void doInBackground(Void... nothings) {
filterSearchTaskCallbacks.performFilterSearch();
return null;
}
@Override
protected void onCancelled() {
Log.i("TASK CANCELLED", "THE TASK NUMBER " + getTaskNum() + " HAS BEEN CANCELLED");
}
@Override
protected void onPostExecute(Void nothing) {
filterSearchTaskCallbacks.onPostExecute();
running = false;
}
}
}
它有一个我的Activity实现的接口(TaskCallbacks):
public void onPreExecute() {
}
public void performFilterSearch() {
if (!filterSearchTask.isCancelled()) {
adapter.setFilterSearchTask(filterSearchTask);
adapter.setConstraint(constraint);
adapter.setStartChangeOffset(startChangeOffset);
adapter.setBeforeChars(beforeChars);
adapter.setCountCharsThatReplacedBefore(countCharsThatReplacedBefore);
adapter.setNotifyOnChange(false);
if (!filterSearchTask.isCancelled()) {
adapter.getFilter().filter(constraint);
}
}
}
public void onPostExecute() {
}
过滤器工作委托给自定义适配器,它包含Filter实现,这里是类:
public class MunicipalitySearchAdapter extends ArrayAdapter<Municipality> {
private ArrayList<Municipality> municipalities;
private ArrayList<Municipality> allMunicipalities;
private ArrayList<Municipality> suggestedMunicipalities;
FilterSearchTaskFragment filterSearchTask;
private List<Trieable> triableList;
private Trie municipalityTrie;
private int viewResourceId;
@SuppressWarnings("unchecked")
public MunicipalitySearchAdapter(Context context, int viewResourceId, ArrayList<Municipality> municipalities) {
super(context, viewResourceId, municipalities);
this.municipalities = municipalities;
this.allMunicipalities = (ArrayList<Municipality>) this.municipalities.clone();
this.suggestedMunicipalities = new ArrayList<Municipality>();
this.viewResourceId = viewResourceId;
this.triableList = new ArrayList<Trieable>();
for (Municipality mun : allMunicipalities) {
triableList.add(mun);
}
municipalityTrie = new Trie(triableList, Locale.ITALY);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(this.viewResourceId, null);
}
Municipality municipality = municipalities.get(position);
if (municipality != null) {
TextView munNameTxtView = (TextView) v.findViewById(R.id.name);
TextView proSignTxtView = (TextView) v.findViewById(R.id.sign);
TextView regNameTxtView = (TextView) v.findViewById(R.id.regionName);
if (munNameTxtView != null) {
munNameTxtView.setText(municipality.getName());
}
if (proSignTxtView != null) {
proSignTxtView.setText(municipality.getProvinceSign());
}
if (regNameTxtView != null) {
regNameTxtView.setText(municipality.getRegionName());
}
}
return v;
}
@Override
public Filter getFilter() {
return municipalityFilter;
}
Filter municipalityFilter = new Filter() {
@Override
public String convertResultToString(Object resultValue) {
String str = ((Municipality) (resultValue)).getName();
return str;
}
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterRes = new FilterResults();
if (constraint == null || constraint.length() == 0) {
filterRes.values = allMunicipalities;
filterRes.count = allMunicipalities.size();
}
else {
String constraintString = constraint.toString().trim().toLowerCase(Locale.ITALY);
suggestedMunicipalities.clear();
List<Integer> wordsIndexesList = municipalityTrie.getWordsIndexes(municipalityTrie.getRootVertex(), constraintString);
if (wordsIndexesList != null) {
for (int i = 0; i<wordsIndexesList.size() && !filterSearchTask.isCancelled(); i++) {
int index = wordsIndexesList.get(i);
suggestedMunicipalities.add(allMunicipalities.get(index));
}
}
List<Integer> prefixesIndexesList = municipalityTrie.getPrefixesIndexes(municipalityTrie.getRootVertex(), constraintString);
if (prefixesIndexesList != null) {
for (int i = 0; i<prefixesIndexesList.size() && !filterSearchTask.isCancelled(); i++) {
int index = prefixesIndexesList.get(i);
suggestedMunicipalities.add(allMunicipalities.get(index));
}
}
filterRes.values = suggestedMunicipalities;
filterRes.count = suggestedMunicipalities.size();
}
return filterRes;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results != null && results.count > 0) {
@SuppressWarnings("unchecked")
ArrayList<Municipality> filteredMunicipalities = (ArrayList<Municipality>) results.values;
ArrayList<Municipality> supportMunicipalitiesList = new ArrayList<Municipality>();
notifyDataSetChanged();
clear();
if (!filterSearchTask.isCancelled()) {
for (int i = 0; i < filteredMunicipalities.size() && !filterSearchTask.isCancelled(); i++) {
Municipality mun = filteredMunicipalities.get(i);
supportMunicipalitiesList.add(mun);
}
Iterator<Municipality> municipalityIterator = supportMunicipalitiesList.iterator();
while (municipalityIterator.hasNext() && !filterSearchTask.isCancelled()) {
Municipality municipality = municipalityIterator.next();
add(municipality);
}
}
notifyDataSetInvalidated();
}
}
};
}
过滤操作中使用的Trie类是:
public class Trie {
private Vertex rootVertex;
public Trie(List<Trieable> objectList, Locale locale) {
rootVertex = new Vertex();
for (int i = 0; i<objectList.size(); i++) {
String word = objectList.get(i).toString().toLowerCase(locale);
addWord(rootVertex, word, i);
}
}
public Vertex getRootVertex() {
return rootVertex;
}
public void addWord(Vertex vertex, String word, int index) {
if (word.isEmpty()) {
vertex.addIndexToWordsIndexList(index);
vertex.increaseWordsNumber();
}
else {
vertex.addIndexToPrefixesIndexList(index);
vertex.increasePrefixesNumber();
Character fChar = word.charAt(0);
HashMap<Character, Vertex> vertexSons = vertex.getVertexSons();
if (!vertexSons.containsKey(fChar)) {
vertex.addVertexSon(fChar);
}
word = (word.length() == 1) ? "" : word.substring(1);
addWord(vertexSons.get(fChar), word, index);
}
}
public List<Integer> getWordsIndexes(Vertex vertex, String word) {
if (word.isEmpty()) {
return vertex.getWordsIndexList();
}
else {
Character fChar = word.charAt(0);
if (!(vertex.getVertexSons().containsKey(fChar))) {
return null;
}
else {
word = (word.length() == 1) ? "" : word.substring(1);
return getWordsIndexes(vertex.getVertexSons().get(fChar), word);
}
}
}
public List<Integer> getPrefixesIndexes(Vertex vertex, String prefix) {
if (prefix.isEmpty()) {
return vertex.getPrefixesIndexList();
}
else {
Character fChar = prefix.charAt(0);
if (!(vertex.getVertexSons().containsKey(fChar))) {
return null;
}
else {
prefix = (prefix.length() == 1) ? "" : prefix.substring(1);
return getPrefixesIndexes(vertex.getVertexSons().get(fChar), prefix);
}
}
}
}
每个节点都由Trie的顶点表示,这是类:
public class Vertex {
private HashMap<Character, Vertex> vertexSons;
private List<Integer> wordsIndexList;
private List<Integer> prefixesIndexList;
private int wordsNumber;
private int prefixesNumber;
public Vertex() {
vertexSons = new HashMap<Character, Vertex>();
wordsIndexList = new ArrayList<Integer>();
prefixesIndexList = new ArrayList<Integer>();
wordsNumber = 0;
prefixesNumber = 0;
}
public boolean hasWords() {
if (wordsNumber > 0) {
return true;
}
return false;
}
public boolean hasPrefixes() {
if (prefixesNumber > 0) {
return true;
}
return false;
}
public void addVertexSon(Character character) {
vertexSons.put(character, new Vertex());
}
public void addIndexToWordsIndexList(int index) {
wordsIndexList.add(index);
}
public void addIndexToPrefixesIndexList(int index) {
prefixesIndexList.add(index);
}
public HashMap<Character, Vertex> getVertexSons() {
return vertexSons;
}
public List<Integer> getWordsIndexList() {
return wordsIndexList;
}
public List<Integer> getPrefixesIndexList() {
return prefixesIndexList;
}
public int getWordsNumber() {
return wordsNumber;
}
public int getPrefixesNumber() {
return prefixesNumber;
}
public void increaseWordsNumber() {
wordsNumber++;
}
public void increasePrefixesNumber() {
prefixesNumber++;
}
}
最后,我在这里实例化适配器(在我的Activity中)并向AutocompleteTextView添加一个监听器:
adapter = new MunicipalitySearchAdapter(getApplicationContext(), R.layout.municipality_list_item, ListaComuni);
municipalityEditTxt.setAdapter(adapter);
municipalityEditTxt.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
constraint = s;
startChangeOffset = start;
beforeChars = before;
countCharsThatReplacedBefore = count;
if (filterSearchTask.isRunning()) {
filterSearchTask.cancel();
}
filterSearchTask.start();
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void afterTextChanged(Editable s) {
}
});
municipalityEditText是AutocompleteTextView参考。 所以如果你们这里的某个人遇到同样的问题,你能不能告诉我你是如何让它顺利运作的?请回答我,因为我卡住了!
谢谢!