I would like to use a Java Library inside of my Kotlin Android App, but I am relatively new to Kotlin and need some advice. The Library basically looks like this:
public interface Listener{
void onResult(Result res)
}
public class Client{
public Client(){}
public void setListener(Listener l){}
public void start(){} // Starts Thread(s) (so it's non-blocking), does some server calls, computes result, calls listener.onResult(res) after computation is finished.
public void cancel(){}
}
Yes, I know, I could just call the functions directly and use it like in java, but is that the Kotlin way?
I read, doing a similar task (using an asynchronous function, which takes a callback parameter) would be done by wrapping it in a coroutine/suspend function structure.
But I don't know howto adapt this for my Problem(?) or is it the wrong approach?
If you want to make this into a nice easy Kotlin suspending function, it would be like this:
suspend fun doTheThing() : Result {
val c = Client()
try {
//suspend until the listener fires or we're cancelled
return suspendCancellableCoroutine {
cont ->
c.setListener {
result -> cont.resume(result)
}
c.start()
}
} catch (e: Exception) {
// If someone cancels the parent job, our job will complete exceptionally
// before the client is done. Cancel the client since we don't need it
// anymore
c.cancel()
throw e
}
}
I don't see a way in your interface for the client to indicate failure. If that's part of Result then you probably want to turn that into an exception in the listener
Related
I am still new to Java and i would like to know how i can achieve this scenario. I have a function that performs certain calculations and after it is done i would like to pass the result to another function so that it can send a notification.
My problem is that the second function seems to cause the program to wait for a response eventhough its a void function. As a result my program takes time to return the result becuase it is performing another task which should be independent.
Here is some sudo code to exaplain what i am trying to do :
public class MyCalculationclass {
public String PerformCalculations (Object object){
// perform calculation
sendNotificationToUser(usernotificationToken, calculationValue)
return "Success"
}
public void sendNotificationToUser(String usernotificationToken,String calculationValue ){
// send user the notification
}
}
I would like to notify the void function to run when my calculations are complete in such a manner that i do not have to wait for the void function to run before i get the Success message. How can i achieve this in java.
To make proper use of threads, you should consider creating an executor service:
public class MyCalculationclass {
private final ExecutorService executorService = Executors.newCachedThreadPool();
public String PerformCalculations (Object object){
// perform calculation
executorService.execute(() ->
sendNotificationToUser(usernotificationToken, calculationValue));
return "Success"
}
public void sendNotificationToUser(String usernotificationToken,String calculationValue ){
// send user the notification
}
}
Later on, you may want to replace execute() with submit() to get a Future object. Or even better, use a CompletableFuture.
Use Threads:
new Thread(() -> sendNotificationToUser(usernotificationToken, calculationValue)).start();
instead
sendNotificationToUser(usernotificationToken, calculationValue);
I am newbie in Vert.x.
For example, JDBCClient has non-blocking method
JDBCClient.getConnection(Handler<AsyncResult<SQLConnection>> handler)
When I call it, it is really asynchronous.
jdbcClient.getConnection(result -> { /* this code will execute asynchonous */})
But how can I implement my own component with non-blocking methods?
When I write for example this, it doesnt looks asynchronous. It just will execute method body and then will call passed lambda.
class MyComponent {
public void getSomething(Handler<AsyncResult<String>> handler) {
String result = someHeavyMethodInThisThread();
handler.handle(Future.succeededFuture(result));
}
}
/* later */
/* this code will be blocking, right? */
myComponent.getSomething(res -> { /* ... */ })
Maybe there is way to tell Vert.x that my method should be asynchronous? Some annotation or something else?
There is nothing wrong with your code, your code style, normally will be async because the moment you perform a IO operation or call a vert.x API a async operation will detach you from the current thread (event loop).
In your case you're doing CPU bound code so it does not behave as async and as you stated will just call the lambda. If you want nevertheless make it async you can always wrap your code with runOnContext and that will enqueue it to be run on the next iteration of the event loop, e.g.:
class MyComponent {
public void getSomething(Handler<AsyncResult<String>> handler) {
vertx.runOnContext(v -> {
String result = someHeavyMethodInThisThread();
handler.handle(Future.succeededFuture(result));
});
}
}
I'm designing SDK for Android.
As a web developer, I'm very used to and comfortable with callbacks, and as the SDK will include many async operations, I'm not sure what is the most common or "best" way to implement such a behavior on Android (or Java in general).
I've come up with a couple of options:
1) Listener interface - the developer that will use the SDK will implement a listener interface that will include all the callbacks, for example:
interface ISDKListener {
public void onA();
public void onB();
}
class SDK {
private ISDKListener _listener;
public SDK(ISDKListener listener) {
_listener = listener
}
public void a() {
// Do stuff
_listener.onA();
}
public void b() {
// Do stuff
_listener.onB();
}
}
As a web developer, using JS that looks a bit too much for me, "forcing" the user (developer) to implement all the listeners in advance, when he might no even use all of them.
2) Single listeners setters
Basically set a listener to each async method. For example:
interface ISDKCallback {
public void onComplete();
}
class SDK {
private ISDKCallback _aCb;
private ISDKCallback _bCb;
public void setAListener(ISDKCallback aCb) {
_aCb = aCb
}
public void a() {
// Do stuff
if (_aCb != null) _aCb.onComplete();
}
public void setBListener(ISDKCallback bCb) {
_bCb = bCb
}
public void b() {
// Do stuff
if (_bCb != null) _bCb.onComplete();
}
}
3) Same as #2, but separate success and errors:
interface ISDKCallback {
public void onSuccess();
public void onError(Exception e);
}
class SDK {
private ISDKCallback _aCb;
public void setAListener(ISDKCallback aCb) {
_aCb = aCb
}
public void a() {
try {
// Do stuff
if (_aCb != null) _aCb.onSuccess();
} catch (Exception e) {
if (_aCb != null) _aCb.onError(e);
}
}
}
4) Combining #1 and #3 - a complete listener with all the callbacks, but each callback will be 2 callbacks, one for success and one for errors:
interface ISDKListener {
public void onA();
public void onAError(Exception e);
public void onB();
public void onBError(Exception e);
}
class SDK {
private ISDKListener _listener;
public SDK(ISDKListener listener) {
_listener = listener
}
public void a() {
try {
// Do stuff
_listener.onA();
} catch (Exception e) {
_listener.onAError(e);
}
}
public void b() {
try {
// Do stuff
_listener.onB();
} catch (Exception e) {
_listener.onBError(e);
}
}
}
The 3rd one seems most "natural" for me, due to the separation between success and error (like the promise then and catch on JS) and setting each callback separately. Actually the most natural to me was to pass the callback when I call the method, but I did not found such implementation anywhere in Java as far as I've searched.
Which one is the most common and will be the most "natural" to most Android/Java developers? Are there any other suggestions for implementing callbacks in that platform?
EDIT:
To clarify, the callbacks are either for HTTP responses to HTTP requests or BLE communication, for example method a will send some request over BLE to a BLE peripheral, and the callback for a will be called when the peripheral returned a response (the mobile and peripheral are implementing a client-server protocol over BLE)
I'm not the biggest expert out there but if you're asking which is the most common implementation I would say numer 1. You can take a look at a lot of libraries out there, I used a lot of them myself and this is what I found to be the most used solution.
One good example would be the usage of ExoPlayer (I'm choosing it just because I'm working on it at the moment).
As you can see the activity includes an instance of the player + all the objects it needs like the BandwidthMeter and implements ExoPlayer.EventListener inheriting all the callbacks like onPlayerStateChanged.
Even the Android API itself makes use of this pattern, maybe too much. But this is another topic I guess. A lot of people finds this approach a bit confusing because you end up with a callback hell and I'm with them.
Edit
Another good example of a different approach can be found in the Google API Client (which suits your situation better).
As you can see you connect to the Client with two listener, and you have another optional listener for errors with a different interface and an additional callback.
Conclusion
I guess in the end it really depends on you: solution 1 and 2 both look good to me. Number 3 will work too but I'm not too familiar with it, maybe this is a sign that it's not a widely used pattern in Android Development.
In general, callbacks or listeners interfaces are a valid approach, but I would choose Android LiveData. It's an observational data holder which wraps your data and let others listen to your changes. In your case, I would expose LiveData with some kind of model, and the users of your sdk would then observe your return value of type LiveData for future changes in the data. Thus the users of your sdk won't have to implement nothing.
I've just wrote a blog post where I go over callbacks (as well as event bus and LiveData), describing the scenarios in which we should use one over another and the pros and cons of using one rather than the other. I think it may be useful to you:
When and why to use LiveData
I have the folowing constructor...
#Inject
public EditorPresenter(final EventBus eventBus, final MyView view, final Provider<DataProvider> provider) {
DataProvider provider = provider.get();
provider.getInitData().fire(new Receiver<List<DataElement>>() {
#Override
public void onSuccess(List<DataElement> response) {
LOG.info("seting feed types to {}", response);
EditorPresenter.this.data = response;
}
});
}
This constructor sets the class field data to the values returned in the request factory call.
The problem is this data requires a call to the server and is thus asynchronous.
And this field needs to be set when the constructor returns as other objects/beans depend on it (I'm having subsequent errors that depend on data being initalised).
What is the most efficient and light weight way of handling this scenario with Gin?
I'm hoping that there is something built into GIN that handles this scenario gracefully.
GQuery Promise solves this kind of situations:
Something like:
public void yourMethod(....) {
....
getDataFromServer(provider).then(processData)
.done(new Function() { public void f(){
continueYourFlow();
}})
.fail(new Function() { public void f(){
handleError();
}});
}
protected Promise getDataFromServer(final Provider<DataProvider> provider) {
return new PromiseRF(provider.getInitData());
}
Function proccessData = new Function() { public void f() {
List<DataElement> data = arguments(0);
//do something with your data
}};
should work. If not, just ask!
There is something wrong in your approach. You shouldn't hold all your application waiting for server.
If I understand, some data from server is required before client is initialized. Maybe you should put them in your host page? Or move initialization of presenters to other methods and execute these methods by events.
It might be best to not initialize the rest of your app yet. I'm not sure how your initialization is laid out, but I would not initialize anymore after you inject the instance of your EditorPresenter class.
When your onSuccess call gets triggered, fire an event or call a method that picks up where you would have left off. If you think it will be a while you could throw up a wait screen or some such.
I read answers from similar Q&A
How do you create an asynchronous HTTP request in JAVA? |
Asynchronous programming design pattern |
AsyncTask Android - Design Pattern and Return Values
I see a lot of solutions , but none really satifies me.
Listener way
Once the results are caught, the processing is implemented in onResult method.
public interface GeolocationListener {
public void onResult(Address[] addresses);
public void onError(Exception e);
}
This solution doesn't quite satify me , because I want to handle the results in the main method. I hate this interface because when the response is returned, it is processed in onResult resulting in chains of processing and no way to go back to the "main" method.
The servlet way
public class SignGuestbookServlet extends HttpServlet {
public void doPost(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
// ...
resp.sendRedirect("/guestbook.jsp");
}
}
There is no exposed Java code calling the servlet. All the configuration is done in the web.xml
The way I want
Wait for the response like this
Response a = getResponse();
// wait until the response is received, do not go further
// process
Response b = getResponse();
// wait until the response is received, do not go further
process(a,b);
Is there a design pattern to handle the async request and wait for the response like above ? Other way than the listener.
Please no library or framework.
EDIT
Thanks so far the responses. I didn't give you the full picture so I exposed the Geolocation class
I started the implementation . I don't know how to implement the method . Can someone shows "how to" ? He (or she) must also implement the listener to retrieve the results
private Address getFullAddress (String text, AddressListener listener, ... ){
// new Geolocation(text, listener, options).start()
// implements Geolocation.GeolocationListener
// how to return the Address from the onResult ?
}
First, you should not reject the first two methods you discuss. There are very good reasons people are using those techniques and you should try to learn them instead of creating new ones.
Otherwise, you should look at java.util.concurrent:
ExecutorService es = Executors.newFixedThreadPool(2);
...
Future<Response> responseA = es.submit(responseGetter);
Future<Response> responseB = es.submit(responseGetter);
process(responseA.get(), responseB.get());
where responseGetter is of type Callable<Response> (you must implement the method public Response call()).
Asynchronous code can always be made synchronous. The simplest/crudest way is to make the async call, then enter a while loop that just sleeps the current thread until the value comes back.
Edit: Code that turns an asynchronous callback into synchronous code--again, a crude implementation:
import java.util.concurrent.*;
public class MakeAsynchronousCodeSynchronous {
public static void main(String[] args) throws Exception {
final Listener listener = new Listener();
Runnable delayedTask = new Runnable() {
#Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new IllegalStateException("Shouldn't be interrupted", e);
}
listener.onResult(123);
}
};
System.out.println(System.currentTimeMillis() + ": Starting task");
Executors.newSingleThreadExecutor().submit(delayedTask);
System.out.println(System.currentTimeMillis() + ": Waiting for task to finish");
while (!listener.isDone()) {
Thread.sleep(100);
}
System.out.println(System.currentTimeMillis() + ": Task finished; result=" + listener.getResult());
}
private static class Listener {
private Integer result;
private boolean done;
public void onResult(Integer result) {
this.result = result;
this.done = true;
}
public boolean isDone() {
return done;
}
public Integer getResult() {
return result;
}
}
}
You could also use a CountDownLatch as recommended by hakon's answer. It will do basically the same thing. I would also suggest you get familiar with the java.util.concurrent package for a better way to manage threads. Finally, just because you can do this doesn't make it a good idea. If you're working with a framework that's based on asynchronous callbacks, you're probably much better off learning how to use the framework effectively than trying to subvert it.
Could CountDownLatch help you? In the main method, you call getResponse and then countDownLatch.await(). Pass a count down latch to the getResponse method and then count down once getResponse the result from getResponse is finished:
CountDownLatch latch = new CountDownLatch(1);
Response a = getResponse(latch);
latch.await();
latch = new CountDownLatch(1);
Response b = getResponse(latch);
latch.await();
process(a, b);
Your getResponse needs to call latch.countDown() once it's asynch parts return a result.
e.g.:
public Response getResponse(CountDownLatch latch) {
someAsychBloc(final CountDownLatch latch) {
do work
latch.countDown();
}
}
Essentially you need a "listener" of sorts no matter what. This is because you do not know WHEN your return message will come back, if at all (that is one of the downsides of asynchronous processing...what to do if you do not get a return message).
So you either need to implement a listener that waits for events (ie, it is nudged by the returning message to be processed).
Or you could do a hybrid on that by having a separate thread that "polls" (or pulls) a response area on your service to see if the return message exists.
So it really comes down to whether you want more of a "pull" or "push" method of retrieving messages.
The SCA (Service Component Architecture) framework might be something to consider, but depending on what you are doing, it could be overkill too. But something to consider.
EDIT:
I just found this in the Java SE 6 Javadocs that may be helpful. The
interface CompletionService which abstracts the very thing you care
about --> asynchronous work. I suggest you take a look.
If you want a page flow in a web application, you have to handle in the web way : storing some data either in the session, or cookies or hidden fields, etc.
The problem you're trying to tackle, as far as I understand it, doesn't come from asynchronousness but from the stateless http protocole.
Regards,
Stéphane