问题
I have a ListView and ArrayAdapter set on it. My ListView single row contains TextView and start Button. When click on button the TextView text will be changed every millisecond. I have defined timer for it but when I change TextView text it doesn't appears on my view. It changes only when I call notifyDataSetChanged. But in this case calling notifyDataSetChanged every millisecond, my ListView is crashed. How can I solve this problem? In addition to I want to say that I implemented ArrayAdapter with ViewHolder pattern and overrided all necessary methods.
回答1:
you should use RecyclerView it is a A flexible view for providing a limited elements into a large data set. so you can use it to control how many items should Be loaded on particular conditions. you can read about the RecyclerView here
回答2:
As Harshad wrote, you can use RecyclerView and it's the best way.
If for some reason you don't want, you can update specific list view row manually using this line code:
View convertView = listview.getChildAt(rowIndex - listview.getFirstVisiblePosition());
It's much faster than notifyDataChanged...
回答3:
I made up another solution, like RecyclerView method void notifyItemChanged(int position), create CustomBaseAdapter class just like this:
public abstract class CustomBaseAdapter implements ListAdapter, SpinnerAdapter {
private final CustomDataSetObservable mDataSetObservable = new CustomDataSetObservable();
public boolean hasStableIds() {
return false;
}
public void registerDataSetObserver(DataSetObserver observer) {
mDataSetObservable.registerObserver(observer);
}
public void unregisterDataSetObserver(DataSetObserver observer) {
mDataSetObservable.unregisterObserver(observer);
}
public void notifyDataSetChanged() {
mDataSetObservable.notifyChanged();
}
public void notifyItemChanged(int position) {
mDataSetObservable.notifyItemChanged(position);
}
public void notifyDataSetInvalidated() {
mDataSetObservable.notifyInvalidated();
}
public boolean areAllItemsEnabled() {
return true;
}
public boolean isEnabled(int position) {
return true;
}
public View getDropDownView(int position, View convertView, ViewGroup parent) {
return getView(position, convertView, parent);
}
public int getItemViewType(int position) {
return 0;
}
public int getViewTypeCount() {
return 1;
}
public boolean isEmpty() {
return getCount() == 0;
}
}
Don't forget to create a CustomDataSetObservable class too for mDataSetObservable variable in CustomAdapterClass, like this:
public class CustomDataSetObservable extends Observable<DataSetObserver> {
public void notifyChanged() {
synchronized(mObservers) {
// since onChanged() is implemented by the app, it could do anything, including
// removing itself from {@link mObservers} - and that could cause problems if
// an iterator is used on the ArrayList {@link mObservers}.
// to avoid such problems, just march thru the list in the reverse order.
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
}
}
public void notifyInvalidated() {
synchronized (mObservers) {
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onInvalidated();
}
}
}
public void notifyItemChanged(int position) {
synchronized(mObservers) {
// since onChanged() is implemented by the app, it could do anything, including
// removing itself from {@link mObservers} - and that could cause problems if
// an iterator is used on the ArrayList {@link mObservers}.
// to avoid such problems, just march thru the list in the reverse order.
mObservers.get(position).onChanged();
}
}
}
on class CustomBaseAdapter there is a method notifyItemChanged(int position), and you can call that method when you want update a row wherever you want (from button click or anywhere you want call that method). And voila!, your single row will update instantly..
Hope this solution will help you..
来源:https://stackoverflow.com/questions/33196142/updating-a-single-row-in-android-listview-every-millisecond-from-arrayadapter