使用扩展 BaseAdapter 的自定义适配器刷新 ListView
Refresh ListView with custom adapter that extends BaseAdapter
我正在使用 ListView
,它由扩展 BaseAdapter
的自定义适配器填充。使用 AsyncTask
从外部服务器获取数据,AsyncTask
的 onPostExecute 方法调用 ListActivity
上的方法,设置适配器以显示数据
ListView
还实现了 OnScrollListener
以获取滚动数据并添加到底部。
我有一个带有自定义视图的 ActionBar
(Toolbar
),其中包含 EditText
字段和 Button
单击其中,同样 AsyncTask
被调用以使用从 Toolbar
传递的查询值获取新数据。
问题是,当单击工具栏上的按钮时,我希望 ListView
填充全新数据以替换旧值,而是将新数据附加到列表底部(就像 OnClickListener
被调用)。
我检查了 Link1, Link2 但 none 似乎有帮助
当然,主要的打击是使用 NotifyDataSetChange
,我也在使用它,但不值得。
我设置适配器的方法
public void setBusinesses(ArrayList<BusinessListData> businesses) {
imgFetcher = new BusinessListIconTask(this);
layoutInflator = LayoutInflater.from(this);
if (this.businesses == null || adapter == null) {
this.businesses = new ArrayList<>();
adapter = new BusinessListDataAdapter(this, imgFetcher,
layoutInflator, this.businesses);
businessList.setAdapter(adapter);
}
this.businesses.addAll(businesses);
adapter.notifyDataSetChanged();
/* Activates when scrolling to bottom of list */
businessList.setOnScrollListener(new OnScrollListener() {
public int currentScrollState;
public int currentFirstVisibleItem;
public int currentVisibleItemCount;
public int totalItemCount;
public int lastItem;
boolean isLoading = false;
public void onScrollStateChanged(AbsListView view, int scrollState) {
this.currentScrollState = scrollState;
this.isScrollCompleted();
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
this.currentFirstVisibleItem = firstVisibleItem;
this.currentVisibleItemCount = visibleItemCount;
this.totalItemCount = totalItemCount;
this.lastItem = firstVisibleItem + visibleItemCount;
}
private void isScrollCompleted() {
if (this.lastItem == this.totalItemCount) {
/*** In this way I detect if there's been a scroll which has completed ***/
if (!isLoading) {
isLoading = true;
getScrollData(metroTxt, metroLoc, metroId);
}
} else {
businessList.removeFooterView(footerView);
}
}
});
}
设置带有搜索字段的自定义工具栏
void showCustomView(String metroTxt, String metroLoc, String metroId) {
LayoutInflater mInflater = LayoutInflater.from(this);
if (mCustomView == null)
mCustomView = mInflater.inflate(R.layout.custom_action_bar, null);
mToolbar.removeView(mCustomView);
mToolbar.addView(mCustomView);
Log.d("I'm inside custom view", "txt" + metroTxt);
abKeyword = (CustomAutoCompleteTextView) mCustomView
.findViewById(R.id.ab_keyword);
abLocation = (CustomAutoCompleteTextView) mCustomView
.findViewById(R.id.ab_location);
ab_search = (Button) mCustomView
.findViewById(R.id.ab_search);
abKeyword.append(metroTxt);
abLocation.setVisibility(View.GONE);
ab_search.setVisibility(View.GONE);
abKeyword.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus || !abKeyword.getText().toString().isEmpty() || !abLocation.getText().toString().isEmpty()) {
abLocation.setVisibility(View.VISIBLE);
ab_search.setVisibility(View.VISIBLE);
} else {
abLocation.setVisibility(View.GONE);
ab_search.setVisibility(View.GONE);
}
}
});
abKeyword.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable editable) {
// TODO Auto-generated method stub
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
public void onTextChanged(CharSequence s, int start, int before,
int count) {
String newText = s.toString();
BusinessInfoSuggestionTask autocompleteTask = new BusinessInfoSuggestionTask(BusinessResultListActivity.this);
String acType = "keyword";
if (s.length() >= 1) {
abLocation.setVisibility(View.VISIBLE);
ab_search.setVisibility(View.VISIBLE);
autocompleteTask.execute(newText, acType, cActivity);
} else {
abLocation.setVisibility(View.GONE);
ab_search.setVisibility(View.GONE);
}
}
});
ab_search.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
String abKey = abKeyword.getText().toString();
String abLoc = abLocation.getText().toString();
String abId = "";
getBusinesses(abKey, abLoc, abId);
Log.d("I'm clicked", "button on toolbar clicked");
}
});
}
从服务器获取数据的方法
/* Get Businesses data from server */
private void getBusinesses(String metroTxt, String metroLoc, String metroId) {
// TODO Auto-generated method stub
String first = "first";
BusinessListApiTask spTask = new BusinessListApiTask(
BusinessResultListActivity.this);
try {
spTask.execute(metroTxt, metroLoc, metroId, first);
} catch (Exception e) {
spTask.cancel(true);
}
}
/* Fetch more data on scroll */
private void getScrollData(String metroTxt, String metroLoc, String metroId) {
// TODO Auto-generated method stub
String first = "next";
BusinessListApiTask spTask = new BusinessListApiTask(
BusinessResultListActivity.this);
try {
spTask.execute(metroTxt, metroLoc, metroId, first); //Call AsyncTask to fetch data from server
} catch (Exception e) {
spTask.cancel(true);
}
}
您正在使用 .addAll()
将数据附加到适配器已有的数据。快速修复是在使用 .clear()
.
调用 .addAll()
之前删除所有数据
//...
this.businesses.clear();
this.businesses.addAll(businesses);
adapter.notifyDataSetChanged();
//...
我正在使用 ListView
,它由扩展 BaseAdapter
的自定义适配器填充。使用 AsyncTask
从外部服务器获取数据,AsyncTask
的 onPostExecute 方法调用 ListActivity
上的方法,设置适配器以显示数据
ListView
还实现了 OnScrollListener
以获取滚动数据并添加到底部。
我有一个带有自定义视图的 ActionBar
(Toolbar
),其中包含 EditText
字段和 Button
单击其中,同样 AsyncTask
被调用以使用从 Toolbar
传递的查询值获取新数据。
问题是,当单击工具栏上的按钮时,我希望 ListView
填充全新数据以替换旧值,而是将新数据附加到列表底部(就像 OnClickListener
被调用)。
我检查了 Link1, Link2 但 none 似乎有帮助
当然,主要的打击是使用 NotifyDataSetChange
,我也在使用它,但不值得。
我设置适配器的方法
public void setBusinesses(ArrayList<BusinessListData> businesses) {
imgFetcher = new BusinessListIconTask(this);
layoutInflator = LayoutInflater.from(this);
if (this.businesses == null || adapter == null) {
this.businesses = new ArrayList<>();
adapter = new BusinessListDataAdapter(this, imgFetcher,
layoutInflator, this.businesses);
businessList.setAdapter(adapter);
}
this.businesses.addAll(businesses);
adapter.notifyDataSetChanged();
/* Activates when scrolling to bottom of list */
businessList.setOnScrollListener(new OnScrollListener() {
public int currentScrollState;
public int currentFirstVisibleItem;
public int currentVisibleItemCount;
public int totalItemCount;
public int lastItem;
boolean isLoading = false;
public void onScrollStateChanged(AbsListView view, int scrollState) {
this.currentScrollState = scrollState;
this.isScrollCompleted();
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
this.currentFirstVisibleItem = firstVisibleItem;
this.currentVisibleItemCount = visibleItemCount;
this.totalItemCount = totalItemCount;
this.lastItem = firstVisibleItem + visibleItemCount;
}
private void isScrollCompleted() {
if (this.lastItem == this.totalItemCount) {
/*** In this way I detect if there's been a scroll which has completed ***/
if (!isLoading) {
isLoading = true;
getScrollData(metroTxt, metroLoc, metroId);
}
} else {
businessList.removeFooterView(footerView);
}
}
});
}
设置带有搜索字段的自定义工具栏
void showCustomView(String metroTxt, String metroLoc, String metroId) {
LayoutInflater mInflater = LayoutInflater.from(this);
if (mCustomView == null)
mCustomView = mInflater.inflate(R.layout.custom_action_bar, null);
mToolbar.removeView(mCustomView);
mToolbar.addView(mCustomView);
Log.d("I'm inside custom view", "txt" + metroTxt);
abKeyword = (CustomAutoCompleteTextView) mCustomView
.findViewById(R.id.ab_keyword);
abLocation = (CustomAutoCompleteTextView) mCustomView
.findViewById(R.id.ab_location);
ab_search = (Button) mCustomView
.findViewById(R.id.ab_search);
abKeyword.append(metroTxt);
abLocation.setVisibility(View.GONE);
ab_search.setVisibility(View.GONE);
abKeyword.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus || !abKeyword.getText().toString().isEmpty() || !abLocation.getText().toString().isEmpty()) {
abLocation.setVisibility(View.VISIBLE);
ab_search.setVisibility(View.VISIBLE);
} else {
abLocation.setVisibility(View.GONE);
ab_search.setVisibility(View.GONE);
}
}
});
abKeyword.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable editable) {
// TODO Auto-generated method stub
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
public void onTextChanged(CharSequence s, int start, int before,
int count) {
String newText = s.toString();
BusinessInfoSuggestionTask autocompleteTask = new BusinessInfoSuggestionTask(BusinessResultListActivity.this);
String acType = "keyword";
if (s.length() >= 1) {
abLocation.setVisibility(View.VISIBLE);
ab_search.setVisibility(View.VISIBLE);
autocompleteTask.execute(newText, acType, cActivity);
} else {
abLocation.setVisibility(View.GONE);
ab_search.setVisibility(View.GONE);
}
}
});
ab_search.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
String abKey = abKeyword.getText().toString();
String abLoc = abLocation.getText().toString();
String abId = "";
getBusinesses(abKey, abLoc, abId);
Log.d("I'm clicked", "button on toolbar clicked");
}
});
}
从服务器获取数据的方法
/* Get Businesses data from server */
private void getBusinesses(String metroTxt, String metroLoc, String metroId) {
// TODO Auto-generated method stub
String first = "first";
BusinessListApiTask spTask = new BusinessListApiTask(
BusinessResultListActivity.this);
try {
spTask.execute(metroTxt, metroLoc, metroId, first);
} catch (Exception e) {
spTask.cancel(true);
}
}
/* Fetch more data on scroll */
private void getScrollData(String metroTxt, String metroLoc, String metroId) {
// TODO Auto-generated method stub
String first = "next";
BusinessListApiTask spTask = new BusinessListApiTask(
BusinessResultListActivity.this);
try {
spTask.execute(metroTxt, metroLoc, metroId, first); //Call AsyncTask to fetch data from server
} catch (Exception e) {
spTask.cancel(true);
}
}
您正在使用 .addAll()
将数据附加到适配器已有的数据。快速修复是在使用 .clear()
.
.addAll()
之前删除所有数据
//...
this.businesses.clear();
this.businesses.addAll(businesses);
adapter.notifyDataSetChanged();
//...