2014-09-25 30 views
0

我在列表視圖中有一個chronometer。問題是,有時會泄漏,即使我導航到另一個選項卡或滾動列表視圖項目以外,甚至按下了Home按鈕,我仍然可以看到OnChronometerTickListener每秒執行一次。這似乎是資源的浪費,因爲我只有在實際可見時才需要運行它。列表視圖中的計時器有時會泄漏

有沒有辦法避免這種行爲?請注意,它只是有時會發生。

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方法在我cursorAdaptorbindView()方法來啓動它。

回答

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(在CursorAdapterbindView())時,將其添加到支架:

    Chronometer tmpChronometer = viewHolder.myTimer.init(dt_hitSessionStartTime); 
    if(tmpChronometer != null){ 
        chronometerHolder.add(dt_hitSessionStartTime, tmpChronometer); 
    } 
    
  4. onPause(),停止所有的天文表:

    chronometerHolder.stopAll(); 
    
  5. onResume(),啓動所有天文臺:

    chronometerHolder.startAll(); 
    

當您按下Home鍵,而不是退出應用程序,然後再次打開該應用程序時,bindView()呼叫不被執行。這意味着計時器處於停止狀態。所以它必須在onResume()開始,如#5所示。