Reputation: 2552
I have a ListView
which will host compound Views called TaskView
, which is a visual representation of a Task
. The background work is done in an AsyncTask
and the TaskView
's children (two TextView
s and one ProgressView
) are updated in onProgressUpdate()
. After I'm finished updating the Views, I call listView.invalidateViews()
, which I believe is supposed to redraw all its child Views. However, this is not the case because none of the views change. After setting some breakpoints and observing the values of the various views, I have determined that they do change, but their new values just aren't reflected onscreen
Here is an outline of my AsyncTask
(note: class and method names have been simplified)
private TaskView view;
public Monitor(TaskView view) {
this.view = view;
}
protected Void doInBackground(Void... params) {
// <set up a handler to push events to onProgressUpdate()>
// <do work>
return null;
}
protected void onProgressUpdate(Event... values) {
Task task = view.getTask();
// <update task based on the Event>
view.update(); // Tells view to update its TextViews and ProgressBar
// based on task's values
listView.invalidateViews(); // Refresh ListView views?
}
How can I get ListView
to redraw its children?
As requested, here is TaskAdapter.getView()
public View getView(int position, View convertView, ViewGroup parent) {
Task task = getItem(position);
TaskView view = (TaskView) convertView;
if (view == null) {
// Instantiates a TaskView and sets the Task
view = TaskView.newInstance(getContext(), task);
}
return view;
}
and TaskView.update()
public void update() {
// https://github.com/Todd-Davies/ProgressWheel
progressWheel.setProgress(task.getProgress());
if (task.isIndeterminate()) {
progressWheel.spin();
} else {
progressWheel.stopSpinning();
}
// status and secondaryStatus are TextViews
status.setText(task.getStatus());
secondaryStatus.setText(task.getSecondaryStatus());
}
Upvotes: 2
Views: 90
Reputation: 18977
Use the invalidate()
method for each view you've changed.
Another trick is :
updating the array list object that you pass to the adapter for example if the view that you want to update is at position i do this:
list.remove(i);
list.add(i, new object()); // the new object must have the updated content
adapter.notifyDataSetChange();
Update:
let me tell you the problem again: you have a list with a taskview object ( each row corresponds to a taskview) in each row you have a progrees bar and 2 textviews you want to update some rows
Solution :
protected void onProgressUpdate(Event... values) {
Task task = view.getTask();
task.setProgress() // first change the content of taskView data
task.setStatus()
task.setSecondaryStatus()
// now let the adapter do update the rows
adapter.notifyDataSetChange() // if it dose not work remove task and add to list and then again call notify
}
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater =
(LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.list_item, parent, false);
Task task = getItem(position);
TextView status = view.findViewById();
status.setText(task.getStatus());
Progressbar pb = view.findViewById();
//....
TextView secondaryStatus = view.findViewById();
secondaryStatus.setText(task.getSecondaryStatus());
return view;
}
Upvotes: 0
Reputation: 3640
To refresh the listview with new data call the notifyDataSetChanged()
method of the adapter assigned to the listview.
Upvotes: 3