Android 从计时器更新库/列表视图项目视图
我想从计时器更新UI。这根本不是问题,但当涉及到Gallery/ListView时,它会变得很困难。我有一个带有自定义BaseAdapter的图库。我需要一个计数器为每个(画廊)项目(每个项目计数不同,取决于项目数据)。该计数器应该在主线程之外运行。此外,当只有一个项目可见时,我不想为库中的10个项目运行10个线程。当项目/视图可见时,在adapters getView()方法中定义处理程序并启动线程(计数)不是问题。我可以想到如下代码:Android 从计时器更新库/列表视图项目视图,android,multithreading,listview,gallery,adapter,Android,Multithreading,Listview,Gallery,Adapter,我想从计时器更新UI。这根本不是问题,但当涉及到Gallery/ListView时,它会变得很困难。我有一个带有自定义BaseAdapter的图库。我需要一个计数器为每个(画廊)项目(每个项目计数不同,取决于项目数据)。该计数器应该在主线程之外运行。此外,当只有一个项目可见时,我不想为库中的10个项目运行10个线程。当项目/视图可见时,在adapters getView()方法中定义处理程序并启动线程(计数)不是问题。我可以想到如下代码: 公共类MyAdapter扩展了BaseAdapter{
公共类MyAdapter扩展了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);
//...
}
}
问题是删除不再可见的视图的回调,因为在getView()中,当视图变为可见时,我会被注意到,但我不知道如何获取变为不可见的视图(以及持有人及其处理程序)来删除回调
有(其他)方法解决这个问题吗?找到了一个干净的解决方案(如果有人需要这样的解决方案)。我需要更新一个TextView来设置新的计数器值(每秒)
在BaseAdapters getView中,我将文本视图添加到WeakHashMap。文本视图是地图的关键。如果不再引用键,则将删除键/值映射。所以我不会导致内存泄漏。垃圾收集工做这项工作
一个线程对“计数器对象”进行计数,并用相应的值刷新文本视图(GarbageCollector一直运行,因此在我的例子中,地图主要由3个项目组成,因为图库只显示一个项目。由于GarbageCollection,地图立即被“未使用”清除文本视图(特别是在快速滚动列表/图库时)
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); }