Completion handlers in Java?

2019-03-18 16:47发布

问题:

I've been coding for iOS and I'm quite familiar with the concept of blocks in Objective-C. Now I'm leaning Java for Android and trying to convert some apps from Android to iOS.

I read that there no perfect equivalent of blocks in Java, so I'd like to know what is the best alternative to implement completion handlers or anything that could work similarly.

回答1:

Interface types, in general. You can use Runnable (which is an interface) as Rob suggested if your handler has no parameters and a void return type. But it's simple enough to define your own:

interface CompletionHandler {
    public void handle(String reason);
}

and then to pass it to your own class:

something.setCompletionHandler(new CompletionHandler() {
    @Override
    public void handle(String reason) {
        ...
    }
});

In the other class:

void setCompletionHandler(CompletionHandler h) {
     savedHandler = h;
}

and then call it just by calling the method:

savedHandler.handle("Some mysterious reason");

This sort of thing is done for "listeners" in Java Swing and Android libraries all over the place; see View.OnClickListener, for example.

(P.S. I believe that Java 8 lambdas will be usable with all of these interface examples.)



回答2:

You can do runnables. Obviously, the equivalent of blocks is going to require lambdas which are coming in Java 8, but who knows how long before Android supports them (they are still using JUnit 3.8).

There are a LOT of places in Android where things are done that are like blocks, for instance:

  this.currentConditionsActivity.runOnUiThread(new Runnable() {
        @Override
        public void run() {
            currentConditionsActivity.onLocationChanged(...);
        }
    });
    instrumentation.waitForIdleSync();
    setupViewElements();

As you can see, you have to make an instance of an anonymous class, but in most IDEs, the stupidity of the boilerplate is eased by autofilling. This was done in Android Studio and it put the whole thing in after doing new Runnable() (and if you fold the code, it even shows syntax similar to what lambdas will have).

So that's the state for now. Not as bad many make it seem...