您的位置:首页 > 移动开发 > Android开发

[置顶] Android afterTextChanged中逻辑卡顿的问题

2015-11-09 19:47 597 查看
         最近在进行Android应用开发的过程中,遇到了一个问题,在这里我把它记录下来,希望可以给遇到相似问题的同学们一点启发,同时也是对自己做过的项目的一个小总结。

         我的app有一个界面是完成一个搜索框,我没有使用系统自带的搜索框,而是自定义了个布局,它由一个EditText和一个ListView组成。在EditText的afterTextChanged函数里对我输入EditText的数据进行匹配,从而动态去刷新ListView的显示,显现出一个搜索框的效果。

         在这里出现了一个问题,我在afterTextChanged 需要调用notifyDataSetChanged方法去刷新ListView的显示的时候,EditText和ListView的显示都出现了明显地卡顿,至少延迟个3到5秒,对体验造成了极大的影响。关于我的EditText的代码如下:

        

searchWord.addTextChangedListener(new TextWatcher() {

public void onTextChanged(CharSequence s, int start, int before, int count) {

}

public void beforeTextChanged(CharSequence s, int start, int count,
int after) {

}

public void afterTextChanged(Editable s) {
if (s.length() == 0) {
ivDeleteText.setVisibility(View.GONE);
} else {
ivDeleteText.setVisibility(View.VISIBLE);
}

if (s.length() > 0) {
searchData.clear();
for (int i = 0; i < data.size(); i++) {
if (data.get(i).get("name").toString().contains(s.toString())) {
searchData.add(data.get(i));
}
}
} else {
searchData.clear();
citys_bg.setVisibility(View.VISIBLE);
letter_view.setVisibility(View.VISIBLE);
}
<span style="color:#ff0000;">mAdapter.notifyDataSetChanged();</span>
citys_bg.setVisibility(View.GONE);
letter_view.setVisibility(View.INVISIBLE);
}
});


           通过注释,我发现造成卡顿的原因是上面代码中的红色代码段,也就是listview刷新的代码造成了我们的listview和edittext的延迟。但是这段代码又是我这个实现搜索框的必要代码,几乎不能省去,为此,我还尝试了添加广播的方法,通过广播去通知listview的刷新,但还是一样的效果,在Edittext输入的时候会非常卡顿。

          我觉得很奇怪,所以上网问了一些问题,但是很遗憾,几乎没有人回答,最后,我抱着试一试的心态在stackoverflow上问了这个问题,结果得到了别人的提醒:http://stackoverflow.com/questions/33558489/listview-notifydatasetchanged-very-slow-in-edittext-aftertextchanged-method     会不会是我添加监听的这段代码的位置防止错了呢?

          在这里我还要贴上自己的一段代码:

         

private class MyTask extends AsyncTask<String, ArrayList<HashMap<String, Object>>, ArrayList<HashMap<String, Object>>> {
//onPreExecute方法用于在执行后台任务前做一些UI操作
@Override
protected void onPreExecute() {
Utils.startProgress(FindGartenActivity.this);
}

//doInBackground方法内部执行后台任务,不可在此方法内修改UI
@Override
protected ArrayList<HashMap<String, Object>> doInBackground(String... params) {
//在这里做数据库的加载
dbm=new DBManager(getApplicationContext());
SQLiteDatabase db=dbm.openDatabase();

ArrayList<HashMap<String, Object>> temp_data = new ArrayList<HashMap<String, Object>>();
Cursor cs=db.rawQuery("select * from nbg_district where id = 1 or id = 2 or id = 22 or id = 9 or id = 33 or id = 34 or(level = 2 and upid != 1 and upid != 2 and upid != 22 and upid != 9 and upid != 35 and upid != 36 and upid != 33 and upid != 34)", null);
temp_data.clear();
while(cs.moveToNext()){
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("id",cs.getInt(0));
map.put("name", cs.getString(1));
map.put("level", cs.getInt(2));
map.put("usetype", cs.getInt(3));
map.put("upid", cs.getInt(4));
map.put("alpha", NameSort.getFirstPY(cs.getString(1)).toUpperCase());
temp_data.add(map);
}
SortNames(temp_data);
cs.close();
return temp_data;
}

//onProgressUpdate方法用于更新进度信息

@Override
protected void onProgressUpdate(ArrayList<HashMap<String, Object>>... values) {
super.onProgressUpdate(values);
}

//onPostExecute方法用于在执行完后台任务后更新UI,显示结果
@Override
protected void <span style="color:#ff0000;">onPostExecute</span>(ArrayList<HashMap<String, Object>> result) {
data = result;

initOverlay();
handler = new Handler();
overlayThread = new OverlayThread();
letter_view.setOnTouchingLetterChangedListener(new LetterListViewListener());
adapter = new TeamManagerListViewAdapter(data, FindGartenActivity.this);
mListView.setAdapter(mAdapter);
list_content.setAdapter(adapter);

list_content.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
chooseSecondDistrict(Integer.parseInt(data.get(position).get("id").toString()), data.get(position).get("name").toString());
}
});
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
chooseSecondDistrict(Integer.parseInt(searchData.get(position).get("id").toString()), data.get(position).get("name").toString());
}
});

startLocate();

//创建一个数组,它的长度是position,它的每个元素代表了position到0的距离。
heights = new int[data.size()];
int preheight = 0;
for(int i = 0; i < data.size(); i++){
View item = adapter.getView(i, null, list_content);
item.measure(0, 0);
if(i > 0){
preheight = heights[i- 1];
}
heights[i] = item.getMeasuredHeight() + preheight;
}
}

//onCancelled方法用于在取消执行中的任务时更改UI
@Override
protected void onCancelled() {

}
}


        其实就是标注了红色的onPostExecute方法,我原来是执行了个异步线程,然后在onPostExecute方法中添加了我的EditText的addTextChangedListener监听,如果把ddTextChangedListener监听移动到其他地方,比如我的oncreate这样的函数中去执行,发现明显的卡顿现象就缓解了~

        我查了一下,发现的确有人跟我有类似的问题,其实我的问题不在于EditText,而有可能在与在异步线程的onPostExecute方法中调用adpter的刷新所致。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: