Android listview 计时器每秒运行一次

Posted

技术标签:

【中文标题】Android listview 计时器每秒运行一次【英文标题】:Android listview timer run in every second 【发布时间】:2014-04-24 01:44:30 【问题描述】:

我在 listview 上使用计时器时遇到问题。 在我使用 sqlite 值显示的列表项中。有一个textview 显示数据的最后更新时间和当前时间的时间差。我必须每一秒都显示出来。这样用户就可以知道他更新了多长时间。

我尝试了多种方式。

第一种方式

我尝试在adapter 类中添加计时器。所以为每个项目创建新的计时器。所以应用程序崩溃了,因为许多计时器同时运行。

第二种方式

我尝试使用 adapter.notifyDataSetChanged() 方式。像这样。

Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() 
    @Override
    public void run()  
        if (adapterChatThread != null) 
            adapter.notifyDataSetChanged();
        
        timerHandler.postDelayed(this, 1000); // run every second
    
;
timerRunnable.run();

当点击列表项时,我移动到另一个活动,用户可以回到这个Activity

所以在 Onresume 中我使用了

timerHandler.postDelayed(timerRunnable, 500);

和 OnPause

timerHandler.removeCallbacks(timerRunnable);

问题是数据显示不佳。我的意思是每一秒的数据差异不是一秒。一些时间差是 2 秒、5 秒、.. 等等。

表示计时器没有按预期工作。

第三条路

我使用了一个异步任务,并使用计时器每秒调用它。

class ThreadTimer extends AsyncTask<Void, Void, Void> 
    @Override
    protected Void doInBackground(Void... params) 
        return null;
    

    @Override
    protected void onPostExecute(Void result) 
        if (adapter != null)
            adapter.notifyDataSetChanged();
        super.onPostExecute(result);
    
    

我在这里这样称呼它

Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() 
    @Override
    public void run()  
        new ThreadTimer().execute();
        timerHandler.postDelayed(this, 1000); // run every second
    
;
timerRunnable.run();

上一个问题已触发。 (数据显示不好)

第四条路

这样使用AsyncTask

class ThreadTimer extends AsyncTask<Void, Void, Void> 
    void Sleep(int ms) 
        try 
            Thread.sleep(ms);
         catch (Exception e) 
        
    

    @Override
    protected Void doInBackground(Void... params) 
        while (threadRun) 
            Sleep(1000);
            return null;
        
        return null;
    

    @Override
    protected void onPostExecute(Void result) 
        adapter.notifyDataSetChanged();
        super.onPostExecute(result);
    

我在 OnResume 中调用了这个类。 在暂停时我设置 threadRun= false;

问题是一样的。

请帮帮我。

我的要求是每秒更新列表项。

谢谢。

编辑

这是我的适配器类 textview 更新代码。

Date lastUpdatedTime;
final ChatThreadDAO ctd = new ChatThreadDAO();
long timeForNextResponse = ctd.getLastRespondedTime(vct.get(position).getThread_id());

try 
    if (vct.get(position).getThread_read_status() == 1 && timeForNextResponse > 0) 
        final long respTime = timeForNextResponse;
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        lastUpdatedTime = formatter.parse(vct.get(position).getLast_updated_time());
        final long timeDiff = (new Date()).getTime() - lastUpdatedTime.getTime();
        if (timeDiff <= respTime) 
            timeForNextResponse = respTime - timeDiff;
            ctd.updateTimeRespondToLastMsg(vct.get(position).getThread_id(), timeForNextResponse);
            holder.tvChatTimer.setVisibility(View.VISIBLE);
            holder.tvChatTimer.setText(timeForNextResponse / 1000 + "");
         else 
            ctd.updateTimeRespondToLastMsg(vct.get(position).getThread_id(), 0);
        
     else 
        holder.tvChatTimer.setVisibility(View.INVISIBLE);
    
 catch (ParseException e) 
    e.printStackTrace();

这里是 vct

矢量vct;

我将值分配给适配器类构造函数中的向量。

【问题讨论】:

等等,你是在修改适配器中的数据吗? lastUpdatedTime 必须在您的适配器之外设置,适配器用于处理您的每一行,因此即使它可能工作,您仍然会在每次创建或修改列表视图的一行时设置您的 lastUpdatedTime。每当您更改矢量的内容或通知适配器刷新时,都必须设置 lastUpdatedTime。 非常感谢您。我删除了适配器类中的更新 lastUpdatedTime,它现在可以正常工作了。非常感谢。 当我不滚动它时它起作用了。但是当滚动列表时它显示不正确的值。还有其他方法可以实现吗? 好吧,我无法用您当前的代码来判断,但请记住,您的行是在 GetView() 方法上创建/修改的。因此,您需要在此处进行一些修改,否则您的数组中的数据可能不正确。您可以检查您的数组是否包含正确的值。每次您根据数组滚动时,默认自定义适配器都会创建一行,但大多数时候您会修改它,以便它重新使用自己。但无论哪种方式,您的 get 视图都会调用。 【参考方案1】:

这是一个与您的情况类似的示例。

private class connectionControl extends Thread 
        boolean stop_ = false;

        public void stop_() 
            this.stop_ = true;
        

        public void run() 
            System.out.println("Thread started:" + getClass().getSimpleName());
            while(!this.stop_) 
                try 
                    Thread.sleep(1000);
                    runOnUiThread(new Runnable() 

                        @Override
                        public void run() 
                            // TODO Auto-generated method stub
                            Calendar c = Calendar.getInstance(); 
                            int rightNow = c.get(Calendar.SECOND) + c.get(Calendar.MINUTE)*60;
                            if(rightNow - lastUpdatedTime > 10) 
                                wirelessIcon.setImageResource(R.drawable.wireles-s-red);
                            
                            else if(rightNow - lastUpdatedTime > 5) 
                                wirelessIcon.setImageResource(R.drawable.wirelessyellow);
                            
                            else 
                                wirelessIcon.setImageResource(R.drawable.wirelessgreen);
                            
                        
                    );

                 catch (InterruptedException e) 
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                
            
            System.out.println("Thread stoped:" + getClass().getSimpleName());
        
    

每当您调用适配器的 notifyDataSetChanged() 方法时,您设置 lastUpdatedTime 的方式与您创建 rightNow 的方式相同。

【讨论】:

我建议您使用处理程序来刷新列表视图,因为处理程序正在处理您的 UI 线程。 我把这段代码放在哪里。请看我的编辑帖子。我添加了我的适配器类代码。谢谢。 这是一个线程类来检查你的更新时间。 run() 中的 if 条件是您检查经过时间的条件。您可以更改代码块。您可以将其放在单独的文件中,也可以作为 Activity、片段或您正在使用的任何内容的内部类。您在开始活动时创建一个对象,并在刷新列表的任何位置更改 lastUpdatedTime。编辑:刚刚意识到我将其用作内部类,因为 lastUpdatedTime 是我的超类的变量。如果你把它放在一个单独的文件中,你需要为你的 lastUpdatedTime 准备一个 getter setter 方法。

以上是关于Android listview 计时器每秒运行一次的主要内容,如果未能解决你的问题,请参考以下文章

Android:当活动死亡时,计时器被孤立

Android:ListView 中的多个同时倒计时计时器

android中每秒的Http请求

从ArrayAdapter每毫秒更新Android ListView中的一行

提高 Android ListView 中的滚动平滑度

如何在android中设置计时器?