【问题标题】:Android listview timer run in every secondAndroid listview 计时器每秒运行一次
【发布时间】: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 视图都会调用。

标签: android listview timer android-asynctask


【解决方案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.wirelessred);
                            }
                            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 方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多