我的列表视图中有chronometer。问题是,有时它会被泄露,即使我已经导航到另一个选项卡或滚动列表视图项目之外甚至按下OnChronometerTickListener
按钮,我也可以看到Home
每秒执行一次。这似乎是浪费资源,因为我需要它才能在实际可见的情况下运行。
有没有办法避免这种行为?请注意,它有时只会发生。
public class TimerLayout extends LinearLayout {
private static final String LOG_TAG = "TimerLayout";
Button btn_endTimer;
Button btn_cancelTimer;
Chronometer cmt_timer;
Runnable updateTimerThread;
Handler handler;
public TimerLayout(Context context, AttributeSet attrs) {
super(context,attrs);
setOrientation(LinearLayout.VERTICAL);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.timer, this, true);
cmt_timer = (Chronometer) getChildAt(0);
btn_endTimer = (Button) ((ViewGroup) getChildAt(1)).getChildAt(0);
btn_cancelTimer = (Button) ((ViewGroup) getChildAt(1)).getChildAt(1);
btn_endTimer.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View view){
cmt_timer.stop();
}
});
btn_cancelTimer.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View view){
cmt_timer.stop();
}
});
cmt_timer.setOnChronometerTickListener(new OnChronometerTickListener() {
@Override
public void onChronometerTick(Chronometer arg0) {
if(BuildConfig.DEBUG){Log.d(LOG_TAG,"onChronometerTick.objectid=" + System.identityHashCode(TimerLayout.this));}
}
});
}
public void init(Date startTime){
cmt_timer.stop();
if(startTime!=null){
Date now = new Date();
long elapsedTime = now.getTime() - startTime.getTime();
cmt_timer.setBase(SystemClock.elapsedRealtime() - elapsedTime);
cmt_timer.start();
}
}
}
我在init
的{{1}}方法中调用此类的bindView()
方法启动它。
答案 0 :(得分:1)
诀窍是停止片段/活动的onPause()
中的计时器。
所以我创建了一个容纳计时器的课程:
public class ChronometerHolder {
private WeakHashMap<Date, Chronometer> chronometerMap;
private static final String LOG_TAG = "ChronometerHolder";
public ChronometerHolder() {
chronometerMap = new WeakHashMap<Date, Chronometer>();
}
public void add(Date dt_startTime, Chronometer chronometer){
chronometerMap.put(dt_startTime, chronometer);
}
public void remove(Date dt_startTime){
chronometerMap.remove(dt_startTime);
}
public int getCount(){
return chronometerMap.size();
}
public void startAll() {
// start any chronometers that were paused
if (chronometerMap.size() > 0) {
Set<Entry<Date, Chronometer>> set = chronometerMap.entrySet();
Iterator<Entry<Date, Chronometer>> iterator = set.iterator();
Entry<Date, Chronometer> entry;
while (iterator.hasNext()) {
entry = (Entry<Date, Chronometer>) iterator.next();
entry.getValue().start();
}
}
}
}
public void stopAll() {
// stop any chronometers that might be running
if (chronometerMap.size() > 0) {
Set<Entry<Date, Chronometer>> set = chronometerMap.entrySet();
Iterator<Entry<Date, Chronometer>> iterator = set.iterator();
Entry<Date, Chronometer> entry;
while (iterator.hasNext()) {
entry = (Entry<Date, Chronometer>) iterator.next();
entry.getValue().stop();
}
}
}
}
然后我做了以下更改:
从init()
:
public Chronometer init(Date startTime){
Chronometer obj = null;
cmt_timer.stop();
if(startTime!=null){
Date now = new Date();
long elapsedTime = now.getTime() - startTime.getTime();
cmt_timer.setBase(SystemClock.elapsedRealtime() - elapsedTime);
cmt_timer.start();
obj = cmt_timer;
}
return obj;
}
在片段中,实例化持有者类:
ChronometerHolder chronometerHolder = new ChronometerHolder();
每次初始化chrononmeter(在bindView()
的{{1}}中)时,请将其添加到持有者:
CursorAdapter
在Chronometer tmpChronometer = viewHolder.myTimer.init(dt_hitSessionStartTime);
if(tmpChronometer != null){
chronometerHolder.add(dt_hitSessionStartTime, tmpChronometer);
}
中,停止所有计时器:
onPause()
在chronometerHolder.stopAll();
中,启动所有计时器:
onResume()
当您按Home键而不是退出应用程序,然后再次打开应用程序时,chronometerHolder.startAll();
调用不会执行。这意味着计时器处于停止状态。所以它必须在bindView()
中开始,就像在#5中一样。