I am building a metronome in android with sound and a visual blink and of course both things need to be in sync. The problem is that the audio processing happens inside a background thread and as we all very well know "only the thread that created the thread hierarchy can change it's views" therefore I needed a way to get the UI thread to change the veiew. So how can I update the ui thread in sync with the beat I am producing? Both things don't seem synchronized. Is there a better way to achieve this than the method I depict below?
This is the current code I have:
public class MetronomeService extends Service implements Runnable
{
//Thread
private HandlerThread handlerThread;
private Handler backgroundHandler;
private Handler uiHandler
//Interface to the Fragment that owns the views
@Setter
private Listener listener;
//Colour view
private ColourViewManager colour = null;
@Override
public void onCreate()
{
handlerThread = new HandlerThread("PlayerHandlerThread", Process.THREAD_PRIORITY_AUDIO);
handlerThread.start();
//For packages of work in the background
this.backgroundHandler = new Handler(handlerThread.getLooper());
//To send messages to the UI
this.uiHandler = new Handler(Looper.getMainLooper())
{
@Override
public void handleMessage(@NonNull Message msg)
{
switch (msg.what)
{
case 0:
{
listener.resetState();
break;
}
case 1:
{
colour = listener.blink();
break;
}
}
}
};
super.onCreate();
}
@Override
public void run()
{
uiHandler.sendEmptyMessage(0);
audioGenerator.playTrack(bpm);
while (playingState.get() == TimerState.PLAYING)
{
uiHandler.sendEmptyMessage(1);
if (colour == PulsingColourToggleButton.PulsingColour.YELLOW)
{
audioGenerator.writeSound(AudioGenerator.TICKING);
} else if (colour == PulsingColourToggleButton.PulsingColour.RED)
{
audioGenerator.writeSound(AudioGenerator.TOCKING);
}
audioGenerator.writeSound(AudioGenerator.SILENCE);
}
audioGenerator.destroy();
colour = null;
}
public void start()
{
backgroundHandler.post(this);
}
}
Then on the Fragment class I call the service with a simple
service.start()