1. 程式人生 > >Android進階之ListView實現多條資料同時倒計時功能

Android進階之ListView實現多條資料同時倒計時功能

1 概述

最近在做一個網購APP,有個小功能就是限時搶購商品在限定時間內有優惠活動,我們需要給每個件商品做一個倒計時顯示告訴使用者還剩下多少時間。專案中我們有用到ListView和GridView來載入我們的商品資料,對每條資料(對應一件商品)進行倒計時。倒計時實現方式很多,常用的有以下方式:

1,採用Handle與執行緒的sleep(long)

2,採用Handler的postDelayed(Runnable, long)方法

3,採用Handler與timer及TimerTask結合的方法

在實現過程中也有一小點問題,就是開始實現了計時,但是每當上下拉重新整理時,時間就會錯亂。後來經過調整,終於實現了所要的效果。下面講下用到的實現方式,還有另外一種方式類似,只是把hander及時間 處理放到adapter中了,用的Handler+Timer+TimerTask實現的:

2 Handler+Timer+TimerTask

2.1 ShopActivity

public class ShopActivity extends Activity {

private ListView  lv;
private ShopAdapter pmAdapter;
private Timer timer = new Timer();
private TimerTask timerTask;
private List<MyData> dataList;

@SuppressLint("HandlerLeak")
private Handler mHandler = new
Handler() { public void handleMessage(android.os.Message msg) { if (msg.what == 1) { for (int i = 0; i < mMyMatchList.size(); i++) { //這是伺服器當前時間,以此時間為基數進行倒時計,1000為毫秒 dataList.get(i).setServerDate(Long.valueOf(dataList.get(i).getServerDate())+ 1000 + ""); serverTime = Long.valueOf(mMyMatchList.get(i).getServerDate()); pmAdapter.notifyDataSetChanged(); } } } }; @Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.layout_shop); //接下來要從服務端取到資料,加入dataList中 dataList=new ArrayList<MyData>(); lv= (ListView) this.findViewById(R.id.shop_lv); pmAdapter = new ShopAdapter(ShopActivity.this, this); lv.setAdapter(pmAdapter); timerTask = new TimerTask() { @Override public void run() { Message message = Message.obtain(); message.what = 1; mHandler.sendMessage(message); } }; timer.schedule(timerTask, 1000, 1000); } @Override protected void onResume() { super.onResume(); } @Override protected void onDestroy() { if (null != timer) { timer.cancel(); } super.onDestroy(); } }

2.2 ShopAdapter

最後在介面卡類ShopAdapter中,根據伺服器返回的商品優惠截止時間和伺服器時間,把資料加上去就可以了:

TextView timeTv=findViewById();
timeTv.setText(getTimeFromInt(結束時間-伺服器時間));//getTimeFromInt這個方法是計算時間差並轉換成所需要格式的:

public String getTimeFromInt(long time) {
    if (time <= 0) {
        return "已結束"; 
    }

    long day = time / (1 * 60 * 60 * 24);
    long hour = time / (1 * 60 * 60) % 24;
    long minute = time / (1 * 60) % 60;
    long second = time / (1) % 60;
    return "還剩:" + day + "天" + hour + "小時" + minute + "分" + second + "秒";
}

或者:
 /**
  * 設定時間值
  * @param millisUntilFinished
  * @param tvTime
  */
public void setTime(long millisUntilFinished,TextView tvTime) {
        final int SECONDS = 60;//秒數
        final int MINUTES = 60 * 60;//小時
        long first = 0, twice = 0, third = 0;
        long mtmp = 0, mtmp2 = 0;

        //獲取當前時間總秒數
        first = millisUntilFinished / 1000;
        //小於一分鐘 只顯示秒
        if (first < SECONDS) {
            tvTime.setText("00:00:" + (first < 10 ? "0" + first : first));
        } else if (first < MINUTES) {
            twice = first % 60;
            mtmp = first / 60;
            if (twice == 0) {
                tvTime.setText("00:" + (mtmp < 10 ? "0" + mtmp : mtmp) + ":00");
            } else {
                tvTime.setText("00:" + (mtmp < 10 ? "0" + mtmp : mtmp) + ":" + (twice < 10 ? "0" + twice : twice));
            }
        } else {
            twice = first % 3600;
            mtmp = first / 3600;
            if (twice == 0) {
                tvTime.setText("0" + first / 3600 + ":00:00");
            } else {
                if (twice < SECONDS) {
                    tvTime.setText((mtmp < 10 ? "0" + mtmp : mtmp) + ":00:" + (twice < 10 ? "0" + twice : twice));
                } else {
                    third = twice % 60;
                    mtmp2 = twice / 60;
                    if (third == 0) {
                        tvTime.setText((mtmp < 10 ? "0" + mtmp : mtmp) + ":" + (mtmp2 < 10 ? "0" + mtmp2 : mtmp2) + ":00");
                    } else {
                        tvTime.setText((mtmp < 10 ? "0" + mtmp : mtmp) + ":" + (mtmp2 < 10 ? "0" + mtmp2 : mtmp2) + ":" + third);
                    }
                }
            }
        }
    }