Android:每1分钟更新一次ListView项目

时间:2012-10-16 13:44:32

标签: android listview

我的应用程序中有一个Custom ListView,包含一个ImageView和3-5个TextViews。

其中一个TextViews显示该ListView项目的当前时间指定时间之间的时间差。

赞:发布于5分钟前

问题是,如何每分钟更新一次TextView,而不会对ListView造成任何干扰。

喜欢:如果我在看ListView 5分钟,那么仅此TextView必须从1分钟更改为2分钟,以便每个可见的项目

我尝试了什么:

  1. 使用System.currentTimeMillis() - givenTime[position];
  2. getView()中设置此TextView

    但是如果我不滚动(不调用getView)或更改项目的可见性,TextView将不会更新。

    1. 每1分钟使用一次 timeTask()线程并尝试更新每个项目的TextView
    2. 这里的问题是我得到一个例外:

      android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
      

      此外,我不知道如何从Activity中为每个ListView项更改TextView。

      但这看起来像一个熟悉的案例。

      我怎样才能实现这个目标?

      谢谢

4 个答案:

答案 0 :(得分:37)

使用Handler及其postDelayed方法使列表的适配器无效,如下所示:

final Handler handler = new Handler()
handler.postDelayed( new Runnable() {

    @Override
    public void run() {
        adapter.notifyDataSetChanged();
        handler.postDelayed( this, 60 * 1000 );
    }
}, 60 * 1000 );

您必须只更新主(UI)线程中的UI。

通过在主线程中创建处理程序,您可以确保发布到处理程序的所有内容也在主线程中运行。

答案 1 :(得分:4)

您还可以创建自定义TextView,每隔一分钟或每分钟或每小时更新一次。这可以通过创建扩展TextView的类并在该类中添加Handler来轻松完成。好处是您不必更新整个ListView,TextView将自动更新。

示例:

public class TextViewTimeCounter extends TextView {
private long mStartTime = 0;
private long mTimeNow = 0;
private int mDelay = 0;
private String mPart1 = "";
private String mPart2 = "";

private Handler mHandler;

public TextViewTimeCounter(Context context) {
    super(context, null, 0);
}

public TextViewTimeCounter(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public TextViewTimeCounter(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

public void startTimer(long delay, String part1, String part2){
    mStartTime = System.currentTimeMillis();
    mTimeNow = System.currentTimeMillis();
    mDelay = delay;
    mHandler = new Handler();
    mHandler.postDelayed(r, delay);
    convertDatesToMinutes(mStartTime, mTimeNow);
}

public void stopTimer(){
    if(mHandler != null){
        mHandler = null;
        mStartTime = 0;
        mTimeNow = 0;
    }
}

public boolean isTimerRunning(){
    return mHandler == null? false : true;
}


Runnable r = new Runnable() {
    @Override
    public void run(){
        mTimeNow += mDelay;
        convertDatesToMinutes(mStartTime, mTimeNow);
        if(mHandler != null){
            mHandler.postDelayed(r, mDelay);
        }
    }
};



public void convertDatesToMinutes(long start, long end){
    long secs = (end - start);
    long minute = (secs / (1000 * 60)) % 60;
    long hour = (secs / (1000 * 60 * 60)) % 24;
    String time = String.format(Locale.getDefault(), "%2d hours %2d minutes", hour, minute);

    setText(mPart1 + time + mPart2);
}

用法:

TextViewTimeCounter timer = (TextViewTimeCounter)convertView.findViewById(R.id.start_logging_time_text);
timer.startTimer(10000, "Posted ", " ago");

输出将如下所示:

 Posted 1 hours 5 minutes ago

如果您还要显示秒数,请将convertDatesToMinutes(long start, long end)方法更改为:

public void convertDatesToMinutes(long start, long end){
        long secs = (end - start);
        long second = (secs / 1000) % 60;
        long minute = (secs / (1000 * 60)) % 60;
        long hour = (secs / (1000 * 60 * 60)) % 24;
        String time = String.format(Locale.getDefault(), "%2d hours %2d minutes %2d seconds", hour, minute, second);
        setText(mPart1 + time + mPart2);
}

答案 2 :(得分:3)

使用内置的TimerTask

http://developer.android.com/reference/java/util/TimerTask.html

这是一种坚实的做事方式。

答案 3 :(得分:1)

如果你想在主线程中重复一段时间的动作,你应该使用" schedule" Time.class的方法

mHandler = new Handler();
mTimer = new Timer();
mTimer.schedule(new TimerTask() {
    @Override
    public void run() {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                // run main thread code
            }
        });
    }
}, DELAY_TIME, PERIOD_TIME);