从计时器更新Gallery / ListView项目视图

时间:2012-03-08 00:53:01

标签: android multithreading listview gallery adapter

我想从计时器更新UI。这根本不是问题,但是当涉及到Gallery / ListViews时,它变得困难。我有一个自定义BaseAdapter的图库。我需要一个计数器用于每个(图库)项目(每个项目根据项目数据计算不同)。该计数器应该在主线程之外运行。另外,当只有一个项目可见时,我不想为库的10个项目运行10个线程。定义处理程序并在适配器中启动线程(计数)getView() - 项目/视图可见时的方法不是问题。我可以想到类似下面的代码:

public class MyAdapter extends BaseAdapter {

    static class ViewHolder {
         //...
         public Handler myHandler;
     }

     public View getView(int position, View convertView, ViewGroup parent) {

            //...
            // getView() gets called indefinite so first remove callback because it may be added already        
            holder.myHandler.removeCallbacks(myRunnable);
            holder.myHandler.postDelayed(myRunnable, 0);

            //...
     }

static class ViewHolder { //... public Handler myHandler; } public View getView(int position, View convertView, ViewGroup parent) { //... // getView() gets called indefinite so first remove callback because it may be added already holder.myHandler.removeCallbacks(myRunnable); holder.myHandler.postDelayed(myRunnable, 0); //... }

问题是删除不再可见的视图的回调,因为在getView()中我注意到视图变得可见但我不知道如何获取视图(从而获得持有者及其处理程序)删除回调后变得不可见。

是否有(另一种)方法可以解决这个问题?

1 个答案:

答案 0 :(得分:2)

找到一个干净的解决方案(如果有人需要这样的东西)。我需要更新TextView以设置新的计数器值(每秒)。

在BaseAdapters getView中,我将TextViews添加到WeakHashMap。 TextView是地图的关键。如果不再引用密钥,则将删除键/值映射。所以我不会导致内存泄漏。 GarbageCollector完成了这项工作。

线程计算“计数器对象”并使用相应的值刷新TextViews(GarbageCollector一直运行,所以在我的情况下,地图主要包含3个项目,因为图库只显示一个项目。由于GarbageCollection,地图得到通过列表/图库快速滚动时,特别是“未使用的”TextViews立即清除

BaseAdapter的getView():

private WeakHashMap<TextView, Integer> counterMap = new WeakHashMap<TextView,Integer>();
private Handler counterHandler = new Handler();

public View getView(...) {
    //...
    counterMap.put(holder.tvCounter, position);
    //...
}

柜台:

// Thread decrementing the time of the counter objects and updating the UI
private final Runnable counterTimeTask = new Runnable() {
    public void run() {
        //...
        // decrement the remaining time of all objects
        for (CounterData data : counterDataList) 
            data.decrementTimeLeftInSeconds();

        // iterate through the map and update the containing TextViews
        for (Map.Entry<TextView, Integer> entry : counterMap.entrySet()) {
            TextView tvCounter = entry.getKey();
            Integer position = entry.getValue();
            CounterData data = counterDataList.get(position);
            long timeLeftInSeconds = data.getTimeLeftInSeconds();
            tvCounter.setText(" " + timeLeftInSeconds);
        }

        if (yourCondition)
            counterHandler.postDelayed(this, 1000);
    }
};

启动/停止计数器:

public void startCounter() { counterHandler.post(counterTimeTask); }
public void stopCounter() { counterHandler.removeCallbacks(counterTimeTask); }