Create a interface for an observer:
interface ProgressListener {
void onProgressUpdate(String imagePath, int progress);
}
Let the view holder implement that observer and know the image path:
public class ViewHolder implements ProgressListener {
ImageView imgQueue;
ProgressBar pb;
TextView tv;
String imagePath; //set this in getView!
void onProgressUpdate(String imagePath, int progress) {
if (!this.imagePath.equals(imagePath)) {
//was not for this view
return;
}
pb.post(new Runnable() {
pb.setProgress(progress);
});
}
//your other code
}
The adapter shall hold an map of observers for a particular image path/uri whatever and have an method that is called by the upload/download task. Also add methods to add and remove observer:
public class SelectedAdapter_Test extends BaseAdapter {
private Map<String, ProgressListener> mProgressListener = new HashMap<>();
//your other code
synchronized void addProgressObserver(String imagePath, ProgressListener listener) {
this.mListener.put(imagePath, listener);
}
synchronized void removeProgressObserver(String imagePath) {
this.mListener.remove(imagePath);
}
synchronized void updateProgress(String imagePath, int progress) {
ProgressListener l = this.mListener.get(imagePath);
if (l != null) {
l.onProgressUpdate(imagePath, progress);
}
}
//other code
}
In getView of the adapter register the view holder as an observer:
public View getView(final int i, View convertView, ViewGroup viewGroup) {
//other code
holder.imagePath = data.get(i).getSdcardPath();
this.addProgressObserver(holder.imagePath, holder);
return convertView;
}
The problem right now is, that we register the observer but don't unregister. So let the adapter implement the View.addOnAttachStateChangeListener:
public class SelectedAdapter_Test extends BaseAdapter implements View.addOnAttachStateChangeListener {
//other code
void onViewAttachedToWindow(View v) {
//We ignore this
}
void onViewDetachedFromWindow(View v) {
//View is not visible anymore unregister observer
ViewHolder holder = (ViewHolder) v.getTag();
this.removeProgressObserver(holder.imagePath);
}
//other code
}
Register that observer when you return the view.
public View getView(final int i, View convertView, ViewGroup viewGroup) {
//other code
convertView.addOnAttachStateChangeListener(this);
return convertView;
}
Finally you are able to tell the views what the progress is:
@Override
public void transferred(long num) {
int progress = (int) ((num / (float) totalSize) * 100);
selectedAdapter.onProgressUpdate(listOfPhotos.get(i).getSdcardPath(), progress);
}
One final problem remains, what if the activity is gone while the upload is in progress? You need to check if the activity is still alive. Maybe setting a flag in the adapter to true in onCreate and to false in onDestroy would do the trick. Then the last code fragment could check that flag and not notify the adapter on changes anymore.
So thats basically the idea of how to solve this. Does it work? I don't know I wrote it from scratch without any testing. And even if it does, you still have to manage the states when the progress is 0 or 100. But I leave that to you. Also you might want to change the BaseAdapter for an recyclerView so that we can get rid of the View.addOnAttachStateChangeListener.