Skip to content

Commit 95b1b50

Browse files
authored
AN-7576 main thread actions reduction (#73)
* reduced not needed ui actions and memory allocations (time setup called many times and caused many ui updates) * fixed clock initialization (clock was reinitialized on screen rotation) * little naming updates
1 parent 7cc3e5a commit 95b1b50

File tree

4 files changed

+100
-74
lines changed

4 files changed

+100
-74
lines changed

app/src/main/java/com/chess/clock/activities/ClockTimersActivity.java

+42-44
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import com.chess.clock.views.ClockMenu;
3131
import com.chess.clock.views.ViewUtils;
3232

33+
3334
public class ClockTimersActivity extends BaseActivity implements AdjustTimeDialogFragment.TimeAdjustmentsListener {
3435

3536
private static final String TAG = ClockTimersActivity.class.getName();
@@ -57,8 +58,9 @@ public class ClockTimersActivity extends BaseActivity implements AdjustTimeDialo
5758
/**
5859
* Utils
5960
*/
60-
private View mDecorView;
61-
private TimersState mTimersState;
61+
private View windowDecorView;
62+
private TimersState timerState;
63+
private TimersState timersStatePreviousToPause;
6264
private final CountDownTimer.Callback playerOneCallback = new CountDownTimer.Callback() {
6365
@Override
6466
public void onClockTimeUpdate(long millisUntilFinished) {
@@ -68,7 +70,7 @@ public void onClockTimeUpdate(long millisUntilFinished) {
6870
@Override
6971
public void onClockFinish() {
7072
Log.i(TAG, "Player one loses");
71-
mTimersState = TimersState.PLAYER_ONE_FINISHED;
73+
timerState = TimersState.PLAYER_ONE_FINISHED;
7274
soundManager.playSound(ClockSound.GAME_FINISHED, audioManager);
7375
updateUIState();
7476
}
@@ -97,7 +99,7 @@ public void onClockTimeUpdate(long millisUntilFinished) {
9799
@Override
98100
public void onClockFinish() {
99101
Log.i(TAG, "Player two loses");
100-
mTimersState = TimersState.PLAYER_TWO_FINISHED;
102+
timerState = TimersState.PLAYER_TWO_FINISHED;
101103
soundManager.playSound(ClockSound.GAME_FINISHED, audioManager);
102104
updateUIState();
103105
}
@@ -117,15 +119,15 @@ public void onTotalStageNumber(int stagesNumber) {
117119
playerTwoButton.setStages(stagesNumber);
118120
}
119121
};
120-
private TimersState mTimersStatePreviousToPause;
122+
121123

122124
private final ActivityResultLauncher<Intent> settingsResultLauncher = registerForActivityResult(
123125
new ActivityResultContracts.StartActivityForResult(),
124126
result -> {
125127
if (result.getResultCode() == RESULT_OK) {
126128
// Both states at pause means it's the beginning of the game.
127-
mTimersState = TimersState.PAUSED;
128-
mTimersStatePreviousToPause = TimersState.PAUSED;
129+
timerState = TimersState.PAUSED;
130+
timersStatePreviousToPause = TimersState.PAUSED;
129131
updateUIState();
130132
}
131133
});
@@ -154,7 +156,7 @@ protected void onCreate(Bundle savedInstanceState) {
154156
getProperLandscapeLayout() : R.layout.activity_clock_timers;
155157
setContentView(layout);
156158

157-
mDecorView = getWindow().getDecorView();
159+
windowDecorView = getWindow().getDecorView();
158160
soundManager = new ClockSoundManagerImpl();
159161
soundManager.init(getApplicationContext());
160162

@@ -169,11 +171,11 @@ protected void onCreate(Bundle savedInstanceState) {
169171
restoreState(savedInstanceState);
170172
} else {
171173
// Reset timers state to PAUSED
172-
mTimersState = TimersState.PAUSED;
173-
mTimersStatePreviousToPause = TimersState.PAUSED;
174+
timerState = TimersState.PAUSED;
175+
timersStatePreviousToPause = TimersState.PAUSED;
174176
}
175177

176-
initClock();
178+
initClock(savedInstanceState == null);
177179
}
178180

179181
/**
@@ -186,14 +188,14 @@ public void onWindowFocusChanged(boolean hasFocus) {
186188
boolean isFullScreen = appData.getClockFullScreen();
187189
if (hasFocus && currentApiVersion >= Build.VERSION_CODES.KITKAT) {
188190
if (isFullScreen) {
189-
mDecorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
191+
windowDecorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
190192
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
191193
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
192194
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
193195
| View.SYSTEM_UI_FLAG_FULLSCREEN
194196
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
195197
} else {
196-
mDecorView.setSystemUiVisibility(0);
198+
windowDecorView.setSystemUiVisibility(0);
197199
}
198200
} else if (hasFocus) {
199201
if (isFullScreen) {
@@ -233,15 +235,15 @@ private int getProperLandscapeLayout() {
233235
private void restoreState(Bundle savedInstanceState) {
234236
if (savedInstanceState.containsKey(STATE_TIMERS_KEY)) {
235237
int state = savedInstanceState.getInt(STATE_TIMERS_KEY);
236-
mTimersState = TimersState.fromInteger(state);
238+
timerState = TimersState.fromInteger(state);
237239
}
238240
if (savedInstanceState.containsKey(STATE_TIMERS_PREVIOUS_PAUSE_KEY)) {
239241
int state = savedInstanceState.getInt(STATE_TIMERS_PREVIOUS_PAUSE_KEY);
240-
mTimersStatePreviousToPause = TimersState.fromInteger(state);
242+
timersStatePreviousToPause = TimersState.fromInteger(state);
241243
}
242244

243245
// Set play/pause toggle btn
244-
if (mTimersState != TimersState.PAUSED) {
246+
if (timerState != TimersState.PAUSED) {
245247
clockMenu.showPause();
246248
}
247249
}
@@ -267,19 +269,15 @@ protected void onDestroy() {
267269

268270
@Override
269271
public void onBackPressed() {
270-
if (mTimersState != TimersState.PAUSED) {
272+
if (timerState != TimersState.PAUSED) {
271273
pauseClock();
272274
}
273275
super.onBackPressed();
274276
}
275277

276-
void initClock() {
278+
void initClock(boolean initializeClockSettings) {
277279
getClockManager().setListeners(playerOneCallback, playerTwoCallback);
278-
/*
279-
Check if timer is already started. Started timer means that Time Controls were set in the clock.
280-
If no time control were set, restore a new timer with last used Time Controls.
281-
*/
282-
if (!getClockManager().isClockStarted()) {
280+
if (initializeClockSettings) {
283281
TimeControlWrapper selectedControl = TimeControlParser.getLastTimeControlOrDefault(this);
284282
getClockManager().setupClock(selectedControl);
285283
Log.d(TAG, "Last controls set.");
@@ -294,19 +292,19 @@ public void resetClock() {
294292
getClockManager().resetClock();
295293

296294
// Both states at pause means it's the beginning of the game.
297-
mTimersState = TimersState.PAUSED;
298-
mTimersStatePreviousToPause = TimersState.PAUSED;
295+
timerState = TimersState.PAUSED;
296+
timersStatePreviousToPause = TimersState.PAUSED;
299297
updateUIState();
300298
soundManager.playSound(ClockSound.RESET_CLOCK, audioManager);
301299
}
302300

303301
public void pauseClock() {
304-
if (mTimersState == TimersState.PLAYER_ONE_RUNNING || mTimersState == TimersState.PLAYER_TWO_RUNNING) {
302+
if (timerState == TimersState.PLAYER_ONE_RUNNING || timerState == TimersState.PLAYER_TWO_RUNNING) {
305303
Log.i(TAG, "Clock paused.");
306-
mTimersStatePreviousToPause = mTimersState;
307-
mTimersState = TimersState.PAUSED;
308-
Log.d(TAG, "Previous state: " + mTimersStatePreviousToPause +
309-
" , current state: " + mTimersState);
304+
timersStatePreviousToPause = timerState;
305+
timerState = TimersState.PAUSED;
306+
Log.d(TAG, "Previous state: " + timersStatePreviousToPause +
307+
" , current state: " + timerState);
310308
getClockManager().pauseClock();
311309

312310
updateUIState();
@@ -321,8 +319,8 @@ public void pauseClock() {
321319
@Override
322320
public void onSaveInstanceState(Bundle saveInstanceState) {
323321
Log.v(TAG, "Saving UI State on instance Bundle ");
324-
saveInstanceState.putInt(STATE_TIMERS_KEY, mTimersState.getValue());
325-
saveInstanceState.putInt(STATE_TIMERS_PREVIOUS_PAUSE_KEY, mTimersStatePreviousToPause.getValue());
322+
saveInstanceState.putInt(STATE_TIMERS_KEY, timerState.getValue());
323+
saveInstanceState.putInt(STATE_TIMERS_PREVIOUS_PAUSE_KEY, timersStatePreviousToPause.getValue());
326324
super.onSaveInstanceState(saveInstanceState);
327325
}
328326

@@ -374,8 +372,8 @@ public void timeSettingsClicked() {
374372

375373
@Override
376374
public void playPauseClicked() {
377-
if (mTimersState == TimersState.PAUSED) {
378-
onPlayerClockClicked(mTimersStatePreviousToPause != TimersState.PLAYER_ONE_RUNNING);
375+
if (timerState == TimersState.PAUSED) {
376+
onPlayerClockClicked(timersStatePreviousToPause != TimersState.PLAYER_ONE_RUNNING);
379377
} else {
380378
pauseClock();
381379
soundManager.playSound(ClockSound.MENU_ACTION, audioManager);
@@ -384,8 +382,8 @@ public void playPauseClicked() {
384382

385383
@Override
386384
public void resetClicked() {
387-
if (mTimersState == TimersState.PLAYER_ONE_RUNNING
388-
|| mTimersState == TimersState.PLAYER_TWO_RUNNING) {
385+
if (timerState == TimersState.PLAYER_ONE_RUNNING
386+
|| timerState == TimersState.PLAYER_TWO_RUNNING) {
389387
pauseClock();
390388
}
391389
showResetClockDialog();
@@ -406,8 +404,8 @@ public void soundClicked() {
406404
* Change buttons and timers UI according to TimerState.
407405
*/
408406
private void updateUIState() {
409-
Log.d(TAG, "Updating UI state to: " + mTimersState);
410-
switch (mTimersState) {
407+
Log.d(TAG, "Updating UI state to: " + timerState);
408+
switch (timerState) {
411409
case PAUSED:
412410
playerOneButton.updateUi(selectedTheme, ClockButton.State.IDLE);
413411
playerTwoButton.updateUi(selectedTheme, ClockButton.State.IDLE);
@@ -436,24 +434,24 @@ private void updateUIState() {
436434
}
437435
clockMenu.updateSoundIcon(soundManager.areSoundsEnabled());
438436
if (clocksDivider != null) {
439-
ViewUtils.showView(clocksDivider, mTimersState == TimersState.PAUSED);
437+
ViewUtils.showView(clocksDivider, timerState == TimersState.PAUSED);
440438
}
441439
}
442440

443441
private void onPlayerClockClicked(boolean firstPlayer) {
444442
ClockPlayer player = ClockPlayer.ofBoolean(firstPlayer);
445443
TimersState playerTimerRunning = firstPlayer ? TimersState.PLAYER_ONE_RUNNING : TimersState.PLAYER_TWO_RUNNING;
446444

447-
Log.i(TAG, "Player " + player.name() + " pressed the clock with state: " + mTimersState + " (previous: " + mTimersStatePreviousToPause + ")");
448-
if (mTimersState == TimersState.PAUSED && mTimersStatePreviousToPause == TimersState.PAUSED) {
445+
Log.i(TAG, "Player " + player.name() + " pressed the clock with state: " + timerState + " (previous: " + timersStatePreviousToPause + ")");
446+
if (timerState == TimersState.PAUSED && timersStatePreviousToPause == TimersState.PAUSED) {
449447
clockMenu.showPause();
450448
}
451-
if (mTimersState == playerTimerRunning || mTimersState == TimersState.PAUSED) {
449+
if (timerState == playerTimerRunning || timerState == TimersState.PAUSED) {
452450
getClockManager().pressClock(player);
453-
mTimersState = firstPlayer ? TimersState.PLAYER_TWO_RUNNING : TimersState.PLAYER_ONE_RUNNING;
451+
timerState = firstPlayer ? TimersState.PLAYER_TWO_RUNNING : TimersState.PLAYER_ONE_RUNNING;
454452
soundManager.playSound(ClockSound.PLAYER_ONE_MOVE, audioManager);
455453
updateUIState();
456-
} else if (mTimersState == TimersState.PLAYER_ONE_FINISHED || mTimersState == TimersState.PLAYER_TWO_FINISHED) {
454+
} else if (timerState == TimersState.PLAYER_ONE_FINISHED || timerState == TimersState.PLAYER_TWO_FINISHED) {
457455
showResetClockDialog();
458456
}
459457
}

app/src/main/java/com/chess/clock/engine/ClockPlayer.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
public enum ClockPlayer {
44
ONE, TWO;
55

6-
public boolean isFirstPlayer() {
7-
return this == ONE;
8-
}
9-
106
public static ClockPlayer ofBoolean(boolean playerOne) {
117
return playerOne ? ONE : TWO;
128
}
9+
10+
public boolean isFirstPlayer() {
11+
return this == ONE;
12+
}
1313
}

app/src/main/java/com/chess/clock/entities/ClockTime.java

+46-21
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,64 @@
33
import android.annotation.SuppressLint;
44

55
public final class ClockTime {
6+
public static int HOUR_MILLIS = 3600000;
7+
public static String CLOCK_FORMAT_HOURS = "%d:%02d:%02d";
8+
public static String CLOCK_FORMAT_MINUTES = "%d:%02d";
69
public final int hours;
710
public final int minutes;
811
public final int seconds;
912
public final long remainingTimeMs;
1013

11-
public static int HOUR_MILLIS = 3600000;
12-
public static String CLOCK_FORMAT_HOURS = "%d:%02d:%02d";
13-
public static String CLOCK_FORMAT_MINUTES = "%d:%02d";
14-
1514
private ClockTime(long timeMs) {
1615
remainingTimeMs = timeMs;
1716
seconds = (int) (timeMs / 1000) % 60;
1817
minutes = (int) ((timeMs / (1000 * 60)) % 60);
1918
hours = (int) ((timeMs / (1000 * 60 * 60)));
2019
}
2120

21+
public static boolean atLeastHourLeft(long timeMs) {
22+
return timeMs >= HOUR_MILLIS;
23+
}
24+
25+
public static String calibratedReadableFormat(long timeMs) {
26+
long calibratedTime = calibrateTime(timeMs);
27+
if (atLeastHourLeft(calibratedTime)) {
28+
return String.format(
29+
CLOCK_FORMAT_HOURS,
30+
(int) ((calibratedTime / (1000 * 60 * 60))),
31+
(int) ((calibratedTime / (1000 * 60)) % 60),
32+
(int) (calibratedTime / 1000) % 60
33+
);
34+
} else {
35+
return String.format(
36+
CLOCK_FORMAT_MINUTES,
37+
(int) ((calibratedTime / (1000 * 60)) % 60),
38+
(int) (calibratedTime / 1000) % 60
39+
);
40+
}
41+
}
42+
43+
public static ClockTime calibrated(long timeMs) {
44+
// calibration
45+
long remainingTime = calibrateTime(timeMs);
46+
return new ClockTime(remainingTime);
47+
}
48+
49+
private static long calibrateTime(long timeMs) {
50+
int rest = (int) (timeMs % 1000);
51+
if (rest > 0 && timeMs > 0) {
52+
return timeMs + 1000;
53+
}
54+
return timeMs;
55+
}
56+
57+
public static ClockTime raw(long timeMs) {
58+
return new ClockTime(timeMs);
59+
}
60+
2261
@SuppressLint("DefaultLocale")
2362
public String toReadableFormat() {
24-
if (atLeaseOneHourLeft()) {
63+
if (atLeastOneHourLeft()) {
2564
return String.format(CLOCK_FORMAT_HOURS, hours, minutes, seconds);
2665
} else {
2766
return String.format(CLOCK_FORMAT_MINUTES, minutes, seconds);
@@ -36,21 +75,7 @@ public String toMinutesFormat() {
3675
return String.format(CLOCK_FORMAT_MINUTES, totalMinutes(), seconds);
3776
}
3877

39-
public boolean atLeaseOneHourLeft() {
40-
return remainingTimeMs >= HOUR_MILLIS;
41-
}
42-
43-
public static ClockTime calibrated(long timeMs) {
44-
// calibration
45-
long remainingTime = timeMs;
46-
int rest = (int) (timeMs % 1000);
47-
if (rest > 0 && timeMs > 0) {
48-
remainingTime = timeMs + 1000;
49-
}
50-
return new ClockTime(remainingTime);
51-
}
52-
53-
public static ClockTime raw(long timeMs) {
54-
return new ClockTime(timeMs);
78+
public boolean atLeastOneHourLeft() {
79+
return atLeastHourLeft(remainingTimeMs);
5580
}
5681
}

app/src/main/java/com/chess/clock/views/ClockButton.java

+8-5
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,14 @@ public class ClockButton extends FrameLayout {
2323

2424
private final int idleTextColor;
2525
private final int runningTextColor;
26-
int idleBgColor = ContextCompat.getColor(getContext(), R.color.gray_light);
27-
2826
private final TextView timeTv;
2927
private final TextView movesTv;
3028
private final TextView controlNameTv;
3129
private final View timeOptions;
3230
private final View stageOne;
3331
private final View stageTwo;
3432
private final View stageThree;
33+
int idleBgColor = ContextCompat.getColor(getContext(), R.color.gray_light);
3534

3635
public ClockButton(Context context, AttributeSet attrs) {
3736
super(context, attrs);
@@ -51,10 +50,14 @@ public ClockButton(Context context, AttributeSet attrs) {
5150
runningTextColor = getResources().getColor(R.color.white);
5251
}
5352

53+
5454
public void setTime(long timeMillis) {
55-
ClockTime clockTime = ClockTime.calibrated(timeMillis);
56-
timeTv.setText(clockTime.toReadableFormat());
57-
if (clockTime.atLeaseOneHourLeft()) {
55+
String readableTime = ClockTime.calibratedReadableFormat(timeMillis);
56+
57+
if (timeTv.getText().equals(readableTime)) return;
58+
59+
timeTv.setText(readableTime);
60+
if (ClockTime.atLeastHourLeft(timeMillis)) {
5861
timeTv.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimension(R.dimen.clock_timer_textSize_small));
5962
} else {
6063
timeTv.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimension(R.dimen.clock_timer_textSize_normal));

0 commit comments

Comments
 (0)