列表视图中的天文台有时会泄露

时间:2014-09-25 05:16:29

标签: android

我的列表视图中有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()方法启动它。

1 个答案:

答案 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();
                }
            }
        }
    }

然后我做了以下更改:

  1. 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;
    
    }
    
  2. 在片段中,实例化持有者类:

    ChronometerHolder chronometerHolder = new ChronometerHolder();
    
  3. 每次初始化chrononmeter(在bindView()的{​​{1}}中)时,请将其添加到持有者:

    CursorAdapter
  4. Chronometer tmpChronometer = viewHolder.myTimer.init(dt_hitSessionStartTime); if(tmpChronometer != null){ chronometerHolder.add(dt_hitSessionStartTime, tmpChronometer); } 中,停止所有计时器:

    onPause()
  5. chronometerHolder.stopAll(); 中,启动所有计时器:

    onResume()
  6. 当您按Home键而不是退出应用程序,然后再次打开应用程序时,chronometerHolder.startAll(); 调用不会执行。这意味着计时器处于停止状态。所以它必须在bindView()中开始,就像在#5中一样。