I'm creating a grid view of "documents" following the view holder/adapter pattern. In the activity I get callbacks from network classes so I need to be able to update each of the grid cells at different times.
The way I'm doing this is by having a Map mapping from the object element (document) to the corresponding view holder. I need to do this because the adapter is recycling the cells so sometimes I could receive a callback to update a cell which is not visible in which case the callback info would be ignored.
I can see that the getView
method of the adapter is getting called many times this way for the position 0. I've been reading that this is normal though.
inflating position 0 *** progressBar 1
recycling position 0
recycling position 0
inflating position 0 *** progressBar 2
recycling position 0
recycling position 0
recycling position 0
recycling position 0
recycling position 0
recycling position 0
One of the UI
elements I need to be updated from the callbacks is a progress bar which I keep track by adding the viewHolder
to my Map associated with the document.
This whole approach works fine for all positions except for the first one. The only difference I could identify was these multiple calls to getView
so I started debugging from there. The progressBar
I'm updating is "progressBar
2" which is the latest that geView
inflated but actually it doesn't respond to the setVisible
(View.VISIBLE). Then I did some changes to the code to update "progressBar
1" and it works.
This means that getView
is inflating twice the same position, but the second time is not being used or showed.
What could I be doing wrong? why progressbar1 works while progressbar2 doesn't? I would expect that getView
would give me the latest view corresponding to a position.
Thanks.
Adapter:
public class DocumentPickerGridViewAdapter extends ArrayAdapter<Document> implements Filterable {
private final DocumentPickerGridViewController picker;
private ArrayList values;
private ArrayList filtered;
private LayoutInflater inflater;
public DocumentPickerGridViewAdapter(Context context, ArrayList values) {
super(context, R.id.documentPickerGridView, values);
this.picker = (DocumentPickerGridViewController) context;
this.filtered = values;
this.values = (ArrayList)values.clone();
inflater = (LayoutInflater) picker.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
ViewHolder oldHolder;
ViewHolder holder;
Document doc = (Document) filtered.get(position);
if (v == null) {
v = inflater.inflate(R.layout.documentpickergriditem, parent, false);
holder = new ViewHolder();
holder.actionView = (Button) v.findViewById(R.id.document_action_button);
holder.coverView = (ImageView) v.findViewById(R.id.documentCoverImage);
holder.archiveButton = (Button) v.findViewById(R.id.document_archive_button);
holder.progressView = (ProgressView) v.findViewById(R.id.documentProgress);
holder.progressBar = (ProgressBar) v.findViewById(R.id.documentCoverImageProgressBar);
picker.allProgressViews.add(holder);
Log.d("MARIANO","adding to allProgressViews "+holder.progressView);
Log.d("MARIANO","inflating position "+position);
v.setTag(holder);
}
else{
// here we are recycling, we should clean old stuff.
holder = (ViewHolder)v.getTag();
synchronized (picker){
oldHolder = picker.documentHoldersMap.get(holder.doc);
}
if(oldHolder != null){
oldHolder.progressView.setVisibility(View.GONE);
oldHolder.progressBar.setVisibility(View.GONE);
}
// Document associated with previous holder it's now out of the adapter visible window.
// we have to remove it from the map so if picker receives any call back we won't update anything.
if(! holder.doc.uuid().equals(doc)){
synchronized (picker){
picker.documentHoldersMap.remove(holder.doc);
}
}
}
holder.doc = doc;
holder.position = position;
synchronized (picker){
picker.documentHoldersMap.put(doc,holder);
}
/*
TODO: check why view extendedGrid starts to measure the size of the grid after gridpicker view has disapear. This causes a ArrayOutofIndexes
exception. DocumentGridPicker view does setDocuments(null); which clears all arrays, but the adapter stays setting as many cells as before.
https://kaldorgroup.jira.com/browse/NEWSWEEK-49
*/
if(picker.documents() != null && picker.documents().size() > 0 ){
picker.setCoverView(holder.coverView, doc);
picker.setActionButton(holder.actionView, doc);
picker.setArchiveButton(holder.archiveButton, doc);
picker.refreshButton(doc);
}
TextView textView = (TextView) v.findViewById(R.id.documentName);
textView.setText(doc.name());
if(position == 0)
Log.d("MARIANO", "progressView: "+holder.progressView);
return v;
}
@Override
public Filter getFilter() {
return new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults result = new FilterResults();
if (constraint.equals(DocumentPickerGridViewController.FILTER_DOWNLOADED)) {
ArrayList items = new ArrayList();
synchronized (this) {
items.addAll(values);
}
for (int i = items.size() - 1; i >= 0; i--) {
if (((Document) items.get(i)).state() != DocumentStates.Downloaded)
items.remove(i);
}
result.count = items.size();
result.values = items;
} else { // ALL ITEMS
synchronized (this) {
result.count = values.size();
result.values = values;
}
}
return result;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
filtered = (ArrayList)results.values;
DocumentPickerGridViewAdapter.this.notifyDataSetChanged();
clear();
for(int i = 0, l = filtered.size(); i < l; i++)
add((Document)filtered.get(i));
notifyDataSetInvalidated();
}
};
}
static class ViewHolder{
ImageView coverView;
Button actionView;
Button archiveButton;
ProgressView progressView;
ProgressBar progressBar;
int position;
Document doc;
}
}
GridView :
<com.kaldorgroup.newsweek.ExpandableGridView
android:id="@+id/documentPickerGridView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:columnWidth="150dp"
android:numColumns="auto_fit"
android:horizontalSpacing="25dp"
android:stretchMode="spacingWidth"
android:verticalSpacing="20dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="5dp"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:isScrollContainer="false"
android:paddingTop="350dp" />