上一篇文章中我們解釋了為什麼要在Android Wear重寫這個計時器app(因為之前已經在“I’m Watch”裡面開發過了),下面我們就來看看程式碼。
我們以這個app的一個核心類開始,這個類負責控制計時器的狀態。這個類包含了4個long型別的變數:第一個代表計時器開始的時間;第二個代表計時器停止的時間(在執行中的話,它就是0);第三個代表計時器停表的時間(如果當前沒有停表,那它也是0),第四個代表總共停表的時長。通過這四個變數我們就可以維持計時器的狀態了,還可以通過計算得到我們需要展示的其他資訊。這個類的基本功能就是都是為了操作這些變數,即維持計時器的這些狀態。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
; html-script: false ] public final class MatchTimer { . . . public static final int MINUTE_MILLIS = 60000; private long start; private long currentStoppage; private long totalStoppages; private long end; . . . public long getElapsed() { if (isRunning()) { return System.currentTimeMillis() - start; } if (end > 0) { return end - start; } return 0; } public boolean isRunning() { return start > 0 && end == 0; } public boolean isPaused() { return currentStoppage > 0; } public int getElapsedMinutes() { return (int) ((System.currentTimeMillis() - start) / MINUTE_MILLIS); } public long getTotalStoppages() { long now = System.currentTimeMillis(); if (isPaused()) { return totalStoppages + (now - currentStoppage); } return totalStoppages; } public long getPlayed() { return getElapsed() - getTotalStoppages(); } public long getStartTime() { return start; } . . . } |
這些都是基本的java程式碼,就不費時間講了。下面的函式更高階一些,可以操作計時器的狀態。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
; html-script: false ] public final class MatchTimer { . . . public void start() { if (end > 0) { start = System.currentTimeMillis() - (end - start); end = 0; } else { start = System.currentTimeMillis(); } save(); } public void stop() { if (isPaused()) { resume(); } end = System.currentTimeMillis(); save(); } public void pause() { currentStoppage = System.currentTimeMillis(); save(); } public void resume() { totalStoppages += System.currentTimeMillis() - currentStoppage; currentStoppage = 0L; save(); } public void reset() { resetWithoutSave(); save(); } private void resetWithoutSave() { start = 0L; currentStoppage = 0L; totalStoppages = 0L; end = 0L; } } |
這些還是基本的Java程式碼,也可以不用講了。只有save()方法我們還沒有見到,這是在類的最後寫的,這個函式才值得的我們講講。
前一篇文章我們討論了關於喚醒機制的問題,我們不需要去維持一個長連線或者後臺服務,只需要維持這幾個計時器的狀態就可以了。我們使用SharedPreference來實現:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
; html-script: false ] public final class MatchTimer implements SharedPreferences.OnSharedPreferenceChangeListener { private static final String KEY_START = "com.stylingandroid.matchtimer.KEY_START"; private static final String KEY_CURRENT_STOPPAGE = "com.stylingandroid.matchtimer.KEY_CURRENT_STOPPAGE"; private static final String KEY_TOTAL_STOPPAGES = "com.stylingandroid.matchtimer.KEY_TOTAL_STOPPAGES"; private static final String KEY_END = "com.stylingandroid.matchtimer.KEY_END"; private static final String PREFERENCES = "MatchTimer"; private final SharedPreferences preferences; public static MatchTimer newInstance(Context context) { SharedPreferences preferences = context.getSharedPreferences(PREFERENCES, Context.MODE_PRIVATE); long start = preferences.getLong(KEY_START, 0); long currentStoppage = preferences.getLong(KEY_CURRENT_STOPPAGE, 0); long totalStoppages = preferences.getLong(KEY_TOTAL_STOPPAGES, 0); long end = preferences.getLong(KEY_END, 0); return new MatchTimer(preferences, start, currentStoppage, totalStoppages, end); } private MatchTimer(SharedPreferences preferences, long start, long currentStoppage, long totalStoppages, long end) { this.preferences = preferences; this.start = start; this.currentStoppage = currentStoppage; this.totalStoppages = totalStoppages; this.end = end; } public void save() { preferences.edit() .putLong(KEY_START, start) .putLong(KEY_CURRENT_STOPPAGE, currentStoppage) .putLong(KEY_TOTAL_STOPPAGES, totalStoppages) .putLong(KEY_END, end) .apply(); } public void registerForUpdates() { preferences.registerOnSharedPreferenceChangeListener(this); } public void unregisterForUpdates() { preferences.unregisterOnSharedPreferenceChangeListener(this); } @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { long value = sharedPreferences.getLong(key, 0L); if (key.equals(KEY_START)) { start = value; } else if (key.equals(KEY_END)) { end = value; } else if (key.equals(KEY_CURRENT_STOPPAGE)) { currentStoppage = value; } else if (key.equals(KEY_TOTAL_STOPPAGES)) { totalStoppages = value; } } . . . } |
我們需要的就是newInstance()方法從SharedPreference中構造一個MatchTimer例項,我們還需要save()方法,可以幫我們把當前的計時器狀態儲存到SharedPreference中。
最後我們要說明的是,如果某一部分持有MatchTimer物件的引用,但是其他物件已經改變了計時器的狀態,就可能會發生異常(見下一篇文章)。所以我們還需要提供一些方法去註冊和登出MatchTImer的例項,在Sharedpreference的值改變時去接收計時器狀態的變化。
現在我們已經定義了一個基本的計時器了,下一篇文章我們會介紹怎麼保持計時器的狀態以及在需要的時候去喚醒這些狀態。
Match Timer 可以在Google Play上下載:Match Timer.