我有一个listview(使用自定义列表适配器),我需要在每一行显示倒计时.
例如,如果我的列表包含4个项目,我将有4行.
在这一点上,我需要处理4个不同的倒计时(每行一个),因为时间不同.
到目前为止,我使用以下方式处理它:在自定义列表适配器中,在getView()方法内部,我创建一个新的CountDownTimer,并在TextView中显示剩余时间.
但是问题是它减慢了很多活动,甚至在最坏的情况下甚至无法正确滚动(因为每次显示一行,都会创建一个新的CountDownTimer).
我搜索了很多更好的解决方案,但没有人满意.
有没有更清洁和更平滑的解决方案来处理listView中的多个倒计时计时器?
谢谢
解决方法
而不是试图显示所有的剩余时间,这个想法是更新可见项目的剩余时间.
请按照以下示例代码,让我知道:
主要活动 :
public class MainActivity extends Activity {
private ListView lvItems;
private List<Product> lstProducts;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lvItems = (ListView) findViewById(R.id.lvItems);
lstProducts = new ArrayList<>();
lstProducts.add(new Product("A",System.currentTimeMillis() + 10000));
lstProducts.add(new Product("B",System.currentTimeMillis() + 20000));
lstProducts.add(new Product("C",System.currentTimeMillis() + 20000));
lstProducts.add(new Product("D",System.currentTimeMillis() + 20000));
lstProducts.add(new Product("E",System.currentTimeMillis() + 20000));
lstProducts.add(new Product("F",System.currentTimeMillis() + 20000));
lstProducts.add(new Product("G",System.currentTimeMillis() + 30000));
lstProducts.add(new Product("H",System.currentTimeMillis() + 20000));
lstProducts.add(new Product("I",System.currentTimeMillis() + 20000));
lstProducts.add(new Product("J",System.currentTimeMillis() + 40000));
lstProducts.add(new Product("K",System.currentTimeMillis() + 20000));
lstProducts.add(new Product("L",System.currentTimeMillis() + 50000));
lstProducts.add(new Product("M",System.currentTimeMillis() + 60000));
lstProducts.add(new Product("N",System.currentTimeMillis() + 20000));
lstProducts.add(new Product("O",System.currentTimeMillis() + 10000));
lvItems.setAdapter(new CountdownAdapter(MainActivity.this,lstProducts));
}
private class Product {
String name;
long expirationTime;
public Product(String name,long expirationTime) {
this.name = name;
this.expirationTime = expirationTime;
}
}
public class CountdownAdapter extends ArrayAdapter<Product> {
private LayoutInflater lf;
private List<ViewHolder> lstHolders;
private Handler mHandler = new Handler();
private Runnable updateRemainingTimeRunnable = new Runnable() {
@Override
public void run() {
synchronized (lstHolders) {
long currentTime = System.currentTimeMillis();
for (ViewHolder holder : lstHolders) {
holder.updateTimeRemaining(currentTime);
}
}
}
};
public CountdownAdapter(Context context,List<Product> objects) {
super(context,objects);
lf = LayoutInflater.from(context);
lstHolders = new ArrayList<>();
startUpdateTimer();
}
private void startUpdateTimer() {
Timer tmr = new Timer();
tmr.schedule(new TimerTask() {
@Override
public void run() {
mHandler.post(updateRemainingTimeRunnable);
}
},1000,1000);
}
@Override
public View getView(int position,View convertView,ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
holder = new ViewHolder();
convertView = lf.inflate(R.layout.list_item,parent,false);
holder.tvProduct = (TextView) convertView.findViewById(R.id.tvProduct);
holder.tvTimeRemaining = (TextView) convertView.findViewById(R.id.tvTimeRemaining);
convertView.setTag(holder);
synchronized (lstHolders) {
lstHolders.add(holder);
}
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.setData(getItem(position));
return convertView;
}
}
private class ViewHolder {
TextView tvProduct;
TextView tvTimeRemaining;
Product mProduct;
public void setData(Product item) {
mProduct = item;
tvProduct.setText(item.name);
updateTimeRemaining(System.currentTimeMillis());
}
public void updateTimeRemaining(long currentTime) {
long timeDiff = mProduct.expirationTime - currentTime;
if (timeDiff > 0) {
int seconds = (int) (timeDiff / 1000) % 60;
int minutes = (int) ((timeDiff / (1000 * 60)) % 60);
int hours = (int) ((timeDiff / (1000 * 60 * 60)) % 24);
tvTimeRemaining.setText(hours + " hrs " + minutes + " mins " + seconds + " sec");
} else {
tvTimeRemaining.setText("Expired!!");
}
}
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/lvItems"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="5dp">
<TextView
android:id="@+id/tvProduct"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="Product Name"
android:textSize="16dp"
android:textStyle="bold" />
<TextView
android:id="@+id/tvTimeRemaining"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="Time Remaining : " />
</LinearLayout>