Skip to content

Optimize Performance

Mitch Todd edited this page Jan 30, 2015 · 1 revision

Google provides some useful Best Practices when it comes to conserving power on the watch. The most fundamental in the mind of Clockwise is minimizing the amount of processing in the onDraw() method. Ideally, this means that onDraw() is reserved mainly for canvas.drawXXX calls. To help achieve this goal, Clockwise exposes an onTimeChanged() callback to allow you to perform your view logic at the appropriate times and not more often than necessary.

As shown in the Watch Face Lifecycle, onTimeChanged() is fired before every onDraw() call. To then perform updates (e.g. clock hand bitmaps) only when specific levels of the time have changed, the WatchFaceTime class exposes the following convenience methods:

boolean hasHourChanged(WatchFaceTime otherTime)
boolean hasMinuteChanged(WatchFaceTime otherTime)
boolean hasSecondChanged(WatchFaceTime otherTime)

The following are 2 common uses of onTimeChanged():

Update Minute Hand Every Second

This is especially useful for an analog watch face that contains an animating/continuous second hand where onDraw() is called every 33ms. In this case, it's unnecessary to also rotate the minute hand (and hour hand for that matter) continuously. You would probably only need to rotate the minute hand every second rather than every 33ms.

@Override
protected long getInteractiveModeUpdateRate() {
    return 33L;
}

@Override
protected void onTimeChanged(WatchFaceTime oldTime, WatchFaceTime newTime) {
    // onTimeChanged called every 33ms. Only update minute hand if 
    // second value has changed
    if (newTime.hasSecondChanged(oldTime)) {
        // get number of degrees to rotate minute hand
        float rotateAngle = TimeUtil.getMinuteDegrees(newTime);

        mMinuteHandCanvas.save();
        mMinuteHandCanvas.rotate(rotateAngle, getWidth() / 2f, getHeight() / 2f);
        mMinuteHandCanvas.drawRect(mMinuteHandRect, mMinuteHandPaint);
        // Perform more complex minute hand drawing here...
        mMinuteHandCanvas.restore();
    }
}

@Override
protected void onDraw(Canvas canvas) {
    // onDraw called every 33ms
    canvas.drawBitmap(mMinuteHandBitmap, 0, 0, mMinuteHandBitmapPaint);
}
Update Time Display Every Minute

It's a bit less offensive to update the time display text continuously than it is to rotate bitmaps, however it is still a lot of unnecessary calls to format the time into a string. Therefore only update the time display whenever the hour or minute value changes is another common use case.

@Override
protected long getInteractiveModeUpdateRate() {
    return 33L;
}

@Override
protected void onTimeChanged(WatchFaceTime oldTime, WatchFaceTime newTime) {
    // onTimeChanged called every 33ms. Only update time text if 
    // hour or minute values have changed
    if (newTime.hasHourChanged(oldTime) || newTime.hasMinuteChanged(oldTime)) {
        // get the current formatted time string
        String timeText = getCurrentTimeText(newTime);

        mTimeCanvas.drawText(timeText, mTimeOffsetX, mTimeOffsetY, mTimePaint);
    }
}

@Override
protected void onDraw(Canvas canvas) {
    // onDraw called every 33ms
    canvas.drawBitmap(mTimeBitmap, 0, 0, null);
}