Is using runnable a better approach?
There is nothing wrong in using a runnable. Your requirement is to run 60fps on good phones and lesser fps on lower end devices:
Is Canvas onDraw timed?
Currently your canvas onDraw() has to be triggered every 16ms to acheive a 60fps animation. To reduce it trigger every 32ms based on your condition.
Note:
We can only trigger the onDraw method by calling invalidate on the canvas view. But we cannot be 100% sure that all your invalidate will result in a redraw. This is where a few frame drops, here and there, will take the sheen out of your animation.
My 2 cents:
When you are dealing with custom views on canvas, using a value animator to perform your redraw(invalidation) will give you flexibility to apply any kind of easing function. And some interesting articles to understand how canvas works so that you can avoid the missed frames.
https://hackernoon.com/android-draw-a-custom-view-ef79fe2ff54b#.vtdmbs95g
https://medium.com/dualcores-studio/make-an-android-custom-view-publish-and-open-source-99a3d86df228#.3jdi1pbt7