I am trying to create a handler to make my api calls using retrofit.
My call work and I get a response, but I would like to know what would be a best practice to return the response.
Here is a simplified version of my code:
public class ApiHandler{
private static String username = "myUsername";
private static String sessionID = "mySessionID";
public static ObjectResponse getObjects(String id){
ClientApi.getApiClient().getObjects(new ObjectRequest(username, sessionID, id), new Callback<ObjectResponse>() {
#Override
public void success(ObjectResponse ObjectResponse, Response response) {
//Request succes
/*I would like to pass the ObjectResponse from the success method to the getObjects method to be able to return them*/
}
#Override
public void failure(RetrofitError error) {
//Request failure
///TODO
System.out.println(error.getResponse().getStatus());
}
});
//I would like to return the ObjectResponse here
return null;
}
}
Then I just call from my fragment: myObjectResponse = ApiHandler.getObjects(id);
My problem is that when the success() method is called in the callback, the getObject() method already ended and I'm not able to return the response.
I saw that I could use an eventbus (otto) to achieve that but I'm not sure how that works or if it even is the best way to do that.
So how could I achieve that?
I finally found my answer.
Using otto I just need to send the objectResponse to the bus as followed:
public class ApiHandler{
private static String username = myUsername;
private static String sessionID = mySessionID;
public static ObjectResponse getObjects(String id){
ClientApi.getApiClient().getObjects(new ObjectRequest(username, sessionID, id), new Callback<ObjectResponse>() {
#Override
public void success(ObjectResponse objectResponse, Response response) {
//Request success
BusProvider.getInstance().post(objectResponse);
/*I would like to pass the ObjectResponse from the success method to the getObjects method to be able to return them*/
}
#Override
public void failure(RetrofitError error) {
//Request failure
///TODO
System.out.println(error.getResponse().getStatus());
}
});
//I would like to return the ObjectResponse here
return null;
}
}
And then in my fragment, register as a receiver:
#Override
public void onPause(){
super.onPause();
//Unregister the fragment from the bus provider
BusProvider.getInstance().unregister(this);
}
#Override
public void onResume(){
super.onResume();
//Register the fragment to be able to receive events through the bus provider
BusProvider.getInstance().register(this);
}
#Subscribe
public void onObjectResponse(ObjectResponse objectResponse){
System.out.println("We did it!!!");
//Do what you want with your object!
}
Before EventBus, an interface was required as a private member of the ApiHandler class (in your case). Now on success, you call your unimplemented method of your interface.
You implement this method somewhere in your UI, and you call getObject() to run in the background. Once the method is successful, it will trigger your interface method which you have implemented in your UI along with the objectResponse to play around with.
EventBus has quite similar concept except that it is a central (or singular) and works in a channel/subscribe manner. Try to use Eventbus + Retrofit + any dependency injector to ease your life.
Related
The way I'm getting callbacks from network requests is via interfaces.
Suppose there are two classes, A & B. Class A initiates all network requests which are performed by B. When B finishes the task, it has to respond to A.
The way I do it is:
public interface MyCallback {
void onTaskDone(String successMessage);
void onTaskFailed(String failMessage);
}
public class A {
onCreate() {
B objectB = new B();
objectB.loginUser(username, password, new MyCallback {
void onTaskDone(successmessage) {
//this is called when task is successful
}
void onTaskFailed(failMessage) {
//this is called when task is failed
});
}
}
}
public class B {
public void loginUser(String username, String password, MyCallback callback) {
//after task is performed
if (task.isSuccessful()) {
callback.onTaskDone("Successful");
} else {
callback.onTaskFailed("Programming is fun they said...");
}
}
}
As you can see, if a task is successful the interface methods are called from B which is received in A.
What my question is: Are there better ways to get callbacks besides using interfaces, or can this technique be made better? One issue I face while implementing this technique is, say I'm using same interface with many methods. In a particular case only one or two methods are used, while the rest remain unused, e,g. class B may never call onTaskFailed(). Is it normal that some methods are completely unused?
Android has a very good third party library like EventBus
https://github.com/greenrobot/EventBus
You can see its documentation, very easy to use.
public class A{
onCreate(){
B objectB = new B();
objectB.loginUser(username,password); //no need to pass callback
#Subscribe(threadMode = ThreadMode.MAIN)
public void onSuccessEvent(SuccessEvent successEvent) {
//this is called when task is successful
}
#Subscribe(threadMode = ThreadMode.MAIN)
public void onErrorEvent(ErrorEventsuccessEvent) {
//this is called when task is failed
}
}
public class B{
public void loginUser(String username, String password){
//after task is performed
if(task.isSuccessful()){
EventBus.getDefault().post(new SuccessEvent("Successful"));
}else{
EventBus.getDefault().post(new ErrorEvent("Programming is fun they said..."));
}
}
Your event classes
public class SuccessEvent {
private String message;
public SuccessEvent(String message) {
this.message=message;
}
}
public class ErrorEvent {
private String message;
public ErrorEvent(String message) {
this.message=message;
}
}
I found the answer to the question at the bottom: i.e the interface methods going unused.
To solve that I used abstract class! i.e an abstract class will implement all the interface callbacks.
Then while passing callback, simply pass the abstract class instance instead of the interface. This way, only the *required method can be overridden for getting the result.
Using Retrofit to check values in database for a login operation. I don't want to move forward without checking this thus want this to occur synchronically.
I am using the execute method instead of enqueue but still getting the result asynchronously. I understand if I do it all in the same class, it might work but I am trying to keep things separately to prevent code duplicate for other future calls. Please advice what I am doing wrong or how I could go about addressing this. Thanks.
Following method occurs when I click a submit button. This method is at my Activity.
Note that everything in this method works. Problem is after startService, it doesn't wait to get information from my rest service and instead jumps straight to the Toast. After that it carries on to perform the execute method which is useless by then.
private void sendLoginRequest(User user){
String token = verificationHelper.createToken(properties.API_KEY, user, 60000);
Retrofit retrofit = retrofitHelper.getRetrofit(properties.BASE_URL);
UserRepository userRepository = retrofit.create(UserRepository.class);
Call<User> call = userRepository.login(token);
if(call != null){
syncService = new SyncService(call);
Intent i = new Intent(this, SyncService.class);
startService(i);
if(verificationHelper.isValidLogin()){
goToMainActivity();
}
}
Toast.makeText(this, "Invalid Login", Toast.LENGTH_SHORT).show();
}
This is my service which gets into the onHandleIntent method after the Toast is called. (Expecting this to be called first and validated before ever going to the Toast).
public class SyncService extends IntentService {
private VerificationHelper verificationHelper = new VerificationHelper();
private PropertiesUtil properties = new PropertiesUtil();
private RetrofitHelper retrofitHelper = new RetrofitHelper(verificationHelper, properties);
private static Call<User> staticCall;
public SyncService(Call<User> call) {
super("SyncService");
staticCall = call;
}
public SyncService(){
super("SyncService");
}
#Override
protected void onHandleIntent(Intent intent) {
retrofitHelper.performCallBackSync(staticCall);
}
}
This is over at my RetrofitHelper for reference.
public class RetrofitHelper {
private VerificationHelper verificationHelper;
private PropertiesUtil properties;
public RetrofitHelper(VerificationHelper verificationHelper, PropertiesUtil properties) {
this.verificationHelper = verificationHelper;
this.properties = properties;
}
public void performCallBackSync(Call<User> call){
try {
// some logic that handles and verifies token values.
verificationHelper.setValidLogin(true);
} catch (IOException e) {
//some error handling
}
}
}
Before using rx.Observable, I used a custom callback with retrofit so I can add some specific logic for handling response/error and not have to do that inside the callback for every request as boilerplate code.
I force users to use the custom callback by putting it in the method signature like this:
#GET("/user_endpoint/")
void getUser(CustomCallback<User> callback);
#GET("/profile_endpoint/")
void getProfile(CustomCallback<Profile> callback);
but now that I'm returning an Observable:
#GET("/user_endpoint/")
Observable<User> getUser();
#GET("/profile_endpoint/")
Observable<Profile> getProfile();
I can't figure out a way to make sure that a custom callback always proxies the error/response.
Also, with retrofit2.0, how can I force the user to use a custom callback with the returned Call object?
CustomCallback for reference:
public abstract class CustomCallback<T> implements Callback<T> {
#Override public final void success(T t, Response response) {
// do some logic
onSuccess(t);
}
#Override public final void failure(RetrofitError error) {
// do something with the error here such as show a Toast
Toast.makeText(Application.getInstance(), error.getLocalizedMessage(), Toast.LENGTH_SHORT).show();
onFailure(error);
}
public abstract void onSuccess(T response);
public abstract void onFailure(Throwable error);
}
Stop. You're thinking this the wrong way.
Instead consider this: You have the normal Retrofit interface:
interface Foo {
#GET("/user_endpoint/")
Observable<User> getUser();
}
And then you have your decorator class:
public class FooDecorator implements Foo {
private Foo delegate = ...; // inject or create the Retrofit instance.
#Override
public Observable<User> getUser() {
return delegate.getUser().doOnNext(...).doOnError(...);
}
}
Then you use only the second class everywhere in your code (preferably just let the DI system use that) and you're set.
If you're feeling adventurous, you could even adapt the RxJavaCallAdapterFactory so that it modifies the returned observables without the need of a custom class.
I am looking for example where I can call loopback's custom method from Android. To explain more, lets say I have a method on server side with name "greet(name)" that will greet someone. I want to invoke that from Android. Any example, or link is ok.
Thanks in advance.
Jahid
In the examples below, I'll assume your model is called Greeter and the static method Greeter.greet is invoked via GET /greeters/greet?name=Alex.
First of all, you need to describe the REST mapping of your method. Then you can call the method using invokeMethod.
public class GreeterRepository extends ModelRepository<Greeter> {
public RestContract createContract() {
RestContract contract = super.createContract();
contract.addItem(new RestContractItem("/" + getNameForRestUrl() + "/greet", "POST"),
getClassName() + ".greet");
return contract;
}
public void greet(name, final VoidCallback callback) {
invokeStaticMethod("greet", ImmutableMap.of("name", name), new Adapter.Callback() {
#Override
public void onError(Throwable t) {
callback.onError(t);
}
#Override
public void onSuccess(String response) {
callback.onSuccess();
}
});
}
}
See ModelRepository.java and Model.java for examples of methods that parse the response body.
Disclaimer: I am one of the developers of LoopBack, loopback-sdk-android is one of my specialisations.
During the most recent Google IO, there was a presentation about implementing restful client applications. Unfortunately, it was only a high level discussion with no source code of the implementation.
In this diagram, on the return path there are various different callbacks to other methods.
How do I declare what these methods are?
I understand the idea of a callback - a piece of code that gets called after a certain event has happened, but I don't know how to implement it. The only way I've implemented callbacks so far have been overriding various methods (onActivityResult for example).
I feel like I have a basic understanding of the design pattern, but I keep on getting tripped up on how to handle the return path.
In many cases, you have an interface and pass along an object that implements it. Dialogs for example have the OnClickListener.
Just as a random example:
// The callback interface
interface MyCallback {
void callbackCall();
}
// The class that takes the callback
class Worker {
MyCallback callback;
void onEvent() {
callback.callbackCall();
}
}
// Option 1:
class Callback implements MyCallback {
void callbackCall() {
// callback code goes here
}
}
worker.callback = new Callback();
// Option 2:
worker.callback = new MyCallback() {
void callbackCall() {
// callback code goes here
}
};
I probably messed up the syntax in option 2. It's early.
When something happens in my view I fire off an event that my activity is listening for:
// DECLARED IN (CUSTOM) VIEW
private OnScoreSavedListener onScoreSavedListener;
public interface OnScoreSavedListener {
public void onScoreSaved();
}
// ALLOWS YOU TO SET LISTENER && INVOKE THE OVERIDING METHOD
// FROM WITHIN ACTIVITY
public void setOnScoreSavedListener(OnScoreSavedListener listener) {
onScoreSavedListener = listener;
}
// DECLARED IN ACTIVITY
MyCustomView slider = (MyCustomView) view.findViewById(R.id.slider)
slider.setOnScoreSavedListener(new OnScoreSavedListener() {
#Override
public void onScoreSaved() {
Log.v("","EVENT FIRED");
}
});
If you want to know more about communication (callbacks) between fragments see here:
http://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity
No need to define a new interface when you can use an existing one: android.os.Handler.Callback. Pass an object of type Callback, and invoke callback's handleMessage(Message msg).
Example to implement callback method using interface.
Define the interface, NewInterface.java.
package javaapplication1;
public interface NewInterface {
void callback();
}
Create a new class, NewClass.java. It will call the callback method in main class.
package javaapplication1;
public class NewClass {
private NewInterface mainClass;
public NewClass(NewInterface mClass){
mainClass = mClass;
}
public void calledFromMain(){
//Do somthing...
//call back main
mainClass.callback();
}
}
The main class, JavaApplication1.java, to implement the interface NewInterface - callback() method. It will create and call NewClass object. Then, the NewClass object will callback it's callback() method in turn.
package javaapplication1;
public class JavaApplication1 implements NewInterface{
NewClass newClass;
public static void main(String[] args) {
System.out.println("test...");
JavaApplication1 myApplication = new JavaApplication1();
myApplication.doSomething();
}
private void doSomething(){
newClass = new NewClass(this);
newClass.calledFromMain();
}
#Override
public void callback() {
System.out.println("callback");
}
}
to clarify a bit on dragon's answer (since it took me a while to figure out what to do with Handler.Callback):
Handler can be used to execute callbacks in the current or another thread, by passing it Messages. the Message holds data to be used from the callback. a Handler.Callback can be passed to the constructor of Handler in order to avoid extending Handler directly. thus, to execute some code via callback from the current thread:
Message message = new Message();
<set data to be passed to callback - eg message.obj, message.arg1 etc - here>
Callback callback = new Callback() {
public boolean handleMessage(Message msg) {
<code to be executed during callback>
}
};
Handler handler = new Handler(callback);
handler.sendMessage(message);
EDIT: just realized there's a better way to get the same result (minus control of exactly when to execute the callback):
post(new Runnable() {
#Override
public void run() {
<code to be executed during callback>
}
});
You can also use LocalBroadcast for this purpose. Here is a quick guide
Create a broadcast receiver:
LocalBroadcastManager.getInstance(this).registerReceiver(
mMessageReceiver, new IntentFilter("speedExceeded"));
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Double currentSpeed = intent.getDoubleExtra("currentSpeed", 20);
Double currentLatitude = intent.getDoubleExtra("latitude", 0);
Double currentLongitude = intent.getDoubleExtra("longitude", 0);
// ... react to local broadcast message
}
This is how you can trigger it
Intent intent = new Intent("speedExceeded");
intent.putExtra("currentSpeed", currentSpeed);
intent.putExtra("latitude", latitude);
intent.putExtra("longitude", longitude);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
unRegister receiver in onPause:
protected void onPause() {
super.onPause();
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
}
asume the main function is the activity that is triggering the event:
fun main() {
val worker = Worker()
worker.setOnCallListener(
object: OnCallListener {
override fun onCall() {
// here we define what should happen
// when the event accures
print("event happend")
}
}
)
// most events will be called from Android system itself
// but in our case we have to call it manually
worker.listener.onCall()
}
the Worker class has an instance of Type OnCallListener interface
and a method to set its value:
class Worker() {
lateinit var listener: OnCallListener
fun setOnCallListener(listener: OnCallListener) {
this.listener = listener
}
}
and the OnCallListener interface looks like this:
interface OnCallListener {
fun onCall()
}