我的应用程序中有一个Custom ListView,包含一个ImageView和3-5个TextViews。
其中一个TextViews显示该ListView项目的当前时间与指定时间之间的时间差。
赞:发布于5分钟前
问题是,如何每分钟更新一次TextView,而不会对ListView造成任何干扰。
喜欢:如果我在看ListView 5分钟,那么仅此TextView必须从1分钟更改为2分钟,以便每个可见的项目
我尝试了什么:
System.currentTimeMillis() - givenTime[position];
但是如果我不滚动(不调用getView)或更改项目的可见性,TextView将不会更新。
这里的问题是我得到一个例外:
android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
此外,我不知道如何从Activity中为每个ListView项更改TextView。
但这看起来像一个熟悉的案例。
我怎样才能实现这个目标?
谢谢
答案 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)
答案 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);