如何在ListView中处理多个倒计时器?

2023-12-15

我有一个列表视图(带有自定义列表适配器),我需要在每一行上显示倒计时。

例如,如果我的列表包含 4 个项目,则我将有 4 行。 此时,我需要处理 4 个不同的倒计时(每行一个),因为时间不同。

enter image description here

到目前为止,我按以下方式处理它:在自定义列表适配器中,在 getView() 方法中,我创建一个新的 CountDownTimer 并在 TextView 中显示剩余时间。

但问题是它大大减慢了活动速度,在最坏的情况下我什至无法正确滚动(因为每次显示一行时,它都会创建一个新的 CountDownTimer)。

我寻找了很多更好的解决方案,但没有人令人满意。

是否有更干净、更流畅的解决方案来处理 listView 内的多个倒计时器?

Thanks


我们的想法不是试图显示所有项目的剩余时间,而是更新可见项目的剩余时间。

请按照以下示例代码告诉我:

主要活动 :

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, 0, 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>

列表项.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>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在ListView中处理多个倒计时器? 的相关文章

  • 如何在应用程序关闭时在 Android 通知中显示操作按钮?

    我有一个安卓应用程序 对于通知 我们必须显示一些操作按钮 当应用程序打开时 我们可以自由地构建通知并显示操作按钮 但是当应用程序关闭时 通知会在 Android 的通知托盘中收到 应用程序开发人员无法控制构建用户界面和操作按钮 我们现在如何
  • 如何从Firebase Firestore实时更新文档中获取修改后的字段或数据? [复制]

    这个问题在这里已经有答案了 我有多个文档 我的问题是我无法获取修改的特定数据 我正在获取完整的文档 db collection employees whereEqualTo OID OID addSnapshotListener new E
  • 如何在android中显示对话框之外的图像?

    我试图在对话框片段的顶部显示配置文件图像 一半在图像之外 我在下面附加了示例对话框 就像那样 并尝试了旧 Stackoverflow 解决方案中的所有 FrameLayout 协作 但我无法存档此内容 请给我正确的解决方案 谢谢 Updat
  • 拖动时跳转 ImageView。 getX() 和 getY() 值正在跳跃

    我创建了一个用于拖动视图的 onTouchListener 如果我使用的话 图像可以顺利拖动getRawX and getRawY 问题是 当您向下放置第二个指针然后抬起第一个指针时 图像将跳转到第二个指针 此 onTouchListene
  • 如何通过我的活动在 Android 中设置铃声?

    我正在尝试找到一种方法来通过 Android 活动中的代码设置新的默认铃声 我已经将铃声下载到bytearray 最后 我设法将默认铃声设置为我下载的铃声 下面不包含下载代码 仅包含将其设置为默认铃声所需的代码 File k new Fil
  • ExpandableListview OnGroupClickListener 未触发

    我正在关注这个 以编程方式折叠 ExpandableListView 中的组 https stackoverflow com questions 4314777 programmatically collapse a group in ex
  • 如何禁用操作栏上“向上”按钮的翻转?

    背景 我做了一个 应用程序管理器 https play google com store apps details id com lb app manager 替代应用程序 我希望添加 RTL 从右到左 语言的翻译 因为我知道在某些 And
  • Android蓝牙java.io.IOException:bt套接字已关闭,读取返回:-1

    我正在尝试编写一个代码 仅连接到运行 Android 5 0 KitKat 的设备上的 目前 唯一配对的设备 无论我尝试了多少方法 我仍然会收到此错误 这是我尝试过的最后一个代码 它似乎完成了我看到人们报告为成功的所有事情 有人能指出我做错
  • 如何使用 SharedPreferences 保存多个值?

    我正在开发一个字典应用程序 在我的应用程序中 我假设用户想要保存最喜欢的单词 我决定使用共享首选项保存这些值 我知道 SQLite 和文件更好 但我坚持使用 SharedPreferences 所以继续使用它 下面是我的代码 Overrid
  • 是否可以通过 Android 应用程序来录音?

    我是一名开发人员 希望创建一个 Android 应用程序来记录电话 这是出于我个人的需要 为了我自己的目的和记录而记录电话 是否有可能做到这一点 是否可以访问麦克风以及通过扬声器发出的声音 我对 Android 开发有点陌生 所以请耐心等待
  • 在android中,将相机预览流到视图上

    我想将 Android 相机的相机预览流式传输到视图上 目的是随后使用 onDraw 将各种内容添加到视图中 我不需要随时实际捕捉图像 它不必是最高质量或每秒最大数量的帧 有谁知道如何做到这一点 将其添加到您的 xml 中
  • 如何为我的 Android Market APK 创建证书?

    我想将我的第一个 APK 应用程序上传到 Android Market 但我收到了此错误 顺便说一下 在 stackoverflow 中搜索时并没有引导我找到正确的链接 市场不接受使用调试证书签名的 APK 创建有效期至少 50 年的新证书
  • 在运行时更改用作背景的 Drawable xml 内的形状纯色

    我有一个 Drawable xml 文件 background xml
  • 安卓。 CalendarView...一次仅显示一个月的日历

    我正在使用 CalendarView 其中我想一次仅查看一个月的日历并滚动查看下个月 但 CalendarView 一次显示所有月份 下面是我的代码
  • 无法使用 findViewById() 找到视图

    我找不到TextView通过致电findViewById 即使 ID 确实存在 OtherActivity public class OtherActivity extends Activity Override protected voi
  • 离子初始加载时间

    我正在使用 Ionic 构建一个简单的应用程序 但我的应用程序在冷启动时的初始加载时间方面存在性能问题 这是我所做的 collection repeat 代替带有 track by 的 ng repeat 原生滚动 overflow scr
  • 如何在android中通过蓝牙向配对设备发送短信?

    在我的应用程序中 我想通过蓝牙发送和接收短信 我可以在列表视图中看到配对设备名称和地址的列表 但是当我尝试向配对设备发送文本时 什么也没有发生 在其他设备中没有收到文本 这是我向配对设备发送消息的代码 private void sendDa
  • Android 标记如何实现拖放?

    你好 我正在 Android 中开发 MapView 应用程序 我有三个标记 我希望稍后能够使用 Google Map API getlocation function 为了尝试一下 我想使用拖放功能移动标记 然后检查位置 任何人都可以通过
  • 丢失应用程序的密钥库文件(但已启用 Google Play 应用程序签名)

    我已经失去了原来的keystore用于签署我的应用程序的文件 我的应用启用了 Google Play 应用签名 如果我联系 Google 支持人员 是否可以重置密钥 以便我可以继续上传到此包 我希望我可以做到这一点 因为应用程序签名已启用
  • LifeCycleAware Fragment 中的片段生命周期事件

    我有一个生命周期感知片段和一个LifecycleObserver class public class MyFragment extends Fragment Override public void onCreate Nullable B

随机推荐

  • 实例化新的内部类时是否需要关键字“this”?

    Oracle Java SE 教程中的另一个示例 它工作正常 但我不确定创建内部类的实例时是否 为什么需要 this 不管我是否取出来 结果似乎都是一样的 为了清楚起见 我指的是 InnerEvenIterator 迭代器 this new
  • 如何将块 div 的角倒角?

    我有以下 HTML 文档
  • 如何解决curl:(35)错误

    如果我在 CentOS 5 机器上运行以下命令 curl LsS https symfony com installer o usr local bin symfony 我收到此错误 curl 35 error 14077410 SSL r
  • 调试闭包编译器编译的 Javascript

    我有一个复杂的 dojo 应用程序 可以在未编译的情况下正常工作 但在使用 Google 编译后闭包编译器 我在某些行为上发现了细微的差异 事实上 调试起来非常困难 而且我无法找到任何有关使用 Google Closure 编译和未编译的
  • 页面请求中的 UTF-8 字节序列无效

    我在页面请求 永久链接 上收到 UTF 8 中的无效字节序列 我不知道为什么也无法重现它 但我确实遇到了很多这样的异常 A ArgumentError occurred in products index invalid byte sequ
  • URL解码混乱

    我有一个引用以下网址的数据库 http en wikipedia org wiki Herbert Gr F6nemeyer 然而 这似乎是一个错误的 URLEncoding 导致 HttpUtility UrlDecode 给我垃圾 和
  • 如何将 django Rest Framework json 查询结果连接到 dgrid/OnDemandGrid

    我的 JSON 存储 django Rest 框架 返回 count next previous 和 results 的键 count 是可用的行数 下一页 是下一页结果的 URL 例如 ids 26 50 previous 是上一页结果的
  • 获取在后台运行的 Java 运行时进程

    我正在编写一个java应用程序 我需要在正在运行的应用程序的整个生命周期中在后台运行一个进程 这是我所拥有的 Runtime getRuntime exec this works ok Process p Runtime getRuntim
  • 是否有一个真正有效的示例来显示 x86_64 上存储加载重新排序的副作用?

    众所周知 在 x86 64 上可以进行 Store Load 重新排序 如果 Store 和 Load 之间没有MFENCE 英特尔 64 和 IA 32 架构 8 2 3 4 可以将早期存储的负载重新排序到不同位置 还已知 在这样的示例中
  • 如何在导航周围创建径向渐变?

    看到围绕导航中心流动的径向渐变了吗 假设我做了一个div那就是导航 我将如何创建如图所示的渐变 注 看背景behind菜单 如果你谈论导航后面的浅棕色光芒 你可以使用 CSS3 来做到这一点 http jsfiddle net Jg8ZC
  • SignalR 自托管 Windows 服务,监听消息

    我正在尝试构建一个自托管 SignalR 的 Windows 服务 我已阅读过诸如此类的教程SignalR 在 ASP Net 上自托管 我注意到 至少看起来 它们是基于广播消息的 并且似乎找不到任何与聆听相关的内容 我需要收听服务内部的消
  • 为字符串创建距离矩阵

    我想加快以下代码的速度 有人能好心地提出一些建议吗 library dplyr library fuzzywuzzyR set seed 42 rm list ls options scipen 999 init FuzzMatcher n
  • Spring Boot 中的 Hystrix 仪表板问题

    我是 Hystrix 仪表板的新手 我已经用 Hystrix 编写了示例应用程序 我想查看 Hystrix 图表 命令指标流 但我收到以下错误 Circuit Unable to connect to Command Metric Stre
  • PDF 中的 JavaScript?

    我制作了一个可编辑的 PDF 供学生索取成绩单 现在 我想限制输入 例如 我只想要他们的 ID 号为数字 并且我只想要姓名字段中的字母 无特殊字符 等 此外 还有一个名为 最后就读年份 的输入 其中输入用户的最后一个学年上大学了 如果输入的
  • 从元素最小值的元组列表中提取元组的优雅方法

    我有一个元组列表 我希望从中得到索引处最小值的元组1 例如 如果我的列表如下 a a 2 ee 3 mm 4 x 1 我希望返回的元组是 x 1 目前我正在使用sorted函数得到这样的结果 min sorted a key lambda
  • 查找图中的连通分量[关闭]

    Closed 这个问题需要多问focused 目前不接受答案 如果我有一个无向图 作为顶点列表实现 如何找到它的连通分量 如何使用快速联盟 使用深度优先搜索 DFS 将所有单独的连接组件标记为已访问 dfs node u for each
  • 删除字符串中连续重复的单词

    我正在尝试编写一个函数来删除字符串中连续的重复单词 保留正则表达式找到的任何匹配项至关重要 换句话说 一只非常非常非常肮脏的狗 应该成为 一只非常脏的狗 我有一个似乎运行良好的正则表达式 基于这篇文章 b S b s 1 但是我不确定如何使
  • 如何从javascript中的值获取对象值的路径

    Example var someObject part1 name Part 1 txt example part2 name Part 2 size 15 qty 60 part3 name Part 3A size 10 qty 20
  • 使用 find 和 iconv 更改文件名

    我尝试使用以下脚本更改文件名 find dir type f exec mv echo iconv f UTF8 t ASCII TRANSLIT 为什么不起作用 我的意思是 当我有一个带有 这样的字符的文件时 它应该将其转换为 a ech
  • 如何在ListView中处理多个倒计时器?

    我有一个列表视图 带有自定义列表适配器 我需要在每一行上显示倒计时 例如 如果我的列表包含 4 个项目 则我将有 4 行 此时 我需要处理 4 个不同的倒计时 每行一个 因为时间不同 到目前为止 我按以下方式处理它 在自定义列表适配器中 在