Java - synchronous callback
java, multithreading
Solution
You could do this with `CountDownLatch`, which might be the lightest synchronization primitive in `java.util.concurrent`:
private boolean findPrinter(final Context ctx) {
final CountDownLatch latch = new CountDownLatch(1);
final boolean[] result = {false};
...
BluetoothDiscoverer.findPrinters(ctx, new DiscoveryHandler() {
...
public void discoveryFinished() {
result[0] = true;
latch.countDown();
}
public void discoveryError(String arg0) {
result[0] = false;
latch.countDown();
}
...
}
// before final return
// wait for 10 seconds for the response
latch.await(10, TimeUnit.SECONDS);
//return the result, it will return false when there is timeout
return result[0];
}
Problem
I have the following code which is executed asynchronously. I would like to make it synchronous in order to follow some logical flow but I cannot work out how. You will see that `scanning` is set to `true` to indicate that the method is still working, at the beginning - I then initiate a `findPrinters(...)` command - this contains a DiscoveryHandler which runs asynchronously - `foundPrinter()` is called each time an item is discovered. `discoveryFinished()` is when the discovery process is successfully completed, and `discoveryError(...)` is called whenever an error occurs. I rely on something being set in my DiscoveryHandler before I would like to return from this method. Hence why I have `while (scanning)` underneath it. But this feels like a hack to me, and not the correct way of doing things. I cannot get `wait()` and `notify()` working. Can someone tell me what the correct way to do this is please? ``` private boolean findPrinter(final Context ctx) { try { scanning = true; BluetoothDiscoverer.findPrinters(ctx, new DiscoveryHandler() { public void foundPrinter(DiscoveredPrinter device) { if (device instanceof DiscoveredPrinterBluetooth) { DiscoveredPrinterBluetooth btDevice = (DiscoveredPrinterBluetooth) device; if (btDevice.friendlyName.startsWith("XXXX")) { try { connection = new BluetoothConnection(btDevice.address); connection.open(); if (connection.isConnected()) { address = btDevice.address; } } catch (Exception ex) { } } } } public void discoveryFinished() { scanning = false; } public void discoveryError(String arg0) { scanning = false; } }); } catch (Exception ex) { } while (scanning) {} return false; } ```