I am creating an app that requires a ListView with an undetermined number of elements, each of which has a timer that counts down from a variable number. I am able to succes
This is an example of the way I do it and it works perfect:
public class TestCounterActivity extends ListActivity
{
TestAdapter adapter;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// Example values
ArrayList values = new ArrayList();
values.add(new Date(1482464366239L));
values.add(new Date(1480464366239L));
values.add(new Date(1470464366239L));
values.add(new Date(1460464366239L));
values.add(new Date(1450464366239L));
values.add(new Date(1440464366239L));
values.add(new Date(1430464366239L));
values.add(new Date(1420464366239L));
values.add(new Date(1410464366239L));
values.add(new Date(1490464366239L));
adapter = new TestAdapter(this, values);
setListAdapter(adapter);
}
@Override
protected void onStop()
{
super.onStop();
// Dont forget to cancel the running timers
adapter.cancelAllTimers();
}
}
And this is the adapter
public class TestAdapter extends ArrayAdapter
{
private final Activity context;
private final List values;
private HashMap counters;
static class TestViewHolder
{
public TextView tvCounter;
}
public TestAdapter(Activity context, List values)
{
super(context, R.layout.test_row, values);
this.context = context;
this.values = values;
this.counters = new HashMap();
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
View rowView = convertView;
if(rowView == null)
{
LayoutInflater inflater = context.getLayoutInflater();
rowView = inflater.inflate(R.layout.test_row, null);
final TestViewHolder viewHolder = new TestViewHolder();
viewHolder.tvCounter = (TextView) rowView.findViewById(R.id.tvCounter);
rowView.setTag(viewHolder);
}
TestViewHolder holder = (TestViewHolder) rowView.getTag();
final TextView tv = holder.tvCounter;
CountDownTimer cdt = counters.get(holder.tvCounter);
if(cdt!=null)
{
cdt.cancel();
cdt=null;
}
Date date = values.get(position);
long currentDate = Calendar.getInstance().getTime().getTime();
long limitDate = date.getTime();
long difference = limitDate - currentDate;
cdt = new CountDownTimer(difference, 1000)
{
@Override
public void onTick(long millisUntilFinished)
{
int days = 0;
int hours = 0;
int minutes = 0;
int seconds = 0;
String sDate = "";
if(millisUntilFinished > DateUtils.DAY_IN_MILLIS)
{
days = (int) (millisUntilFinished / DateUtils.DAY_IN_MILLIS);
sDate += days+"d";
}
millisUntilFinished -= (days*DateUtils.DAY_IN_MILLIS);
if(millisUntilFinished > DateUtils.HOUR_IN_MILLIS)
{
hours = (int) (millisUntilFinished / DateUtils.HOUR_IN_MILLIS);
}
millisUntilFinished -= (hours*DateUtils.HOUR_IN_MILLIS);
if(millisUntilFinished > DateUtils.MINUTE_IN_MILLIS)
{
minutes = (int) (millisUntilFinished / DateUtils.MINUTE_IN_MILLIS);
}
millisUntilFinished -= (minutes*DateUtils.MINUTE_IN_MILLIS);
if(millisUntilFinished > DateUtils.SECOND_IN_MILLIS)
{
seconds = (int) (millisUntilFinished / DateUtils.SECOND_IN_MILLIS);
}
sDate += " "+String.format("%02d",hours)+":"+String.format("%02d",minutes)+":"+String.format("%02d",seconds);
tv.setText(sDate.trim());
}
@Override
public void onFinish() {
tv.setText("Finished");
}
};
counters.put(tv, cdt);
cdt.start();
return rowView;
}
public void cancelAllTimers()
{
Set> s = counters.entrySet();
Iterator it = s.iterator();
while(it.hasNext())
{
try
{
Map.Entry pairs = (Map.Entry)it.next();
CountDownTimer cdt = (CountDownTimer)pairs.getValue();
cdt.cancel();
cdt = null;
}
catch(Exception e){}
}
it=null;
s=null;
counters.clear();
}
}