I am trying to create my own retrofit callback handler because I want to hide a loading screen once the call is done and would rather not repeat the call. I'm getting a Unchecked Assignment warning when using my custom RetrofitCallback and not retrofit2.Callback. What is the correct way to fix this warning?
public abstract class RetrofitCallback<T> implements Callback {
private BaseActivity mContext;
public RetrofitCallback(Context context) {
mContext = (BaseActivity) context;
}
#Override
public void onResponse(Call call, Response response) {
mContext.hideLoading();
onSuccess(response);
}
#Override
public void onFailure(Call call, Throwable t) {
mContext.hideLoading();
}
public abstract void onSuccess(#NonNull Response<T> response);
}
Call being made
service.getSignupCode(request).enqueue(new RetrofitCallback<SignupResponse>(this) {
#Override
public void onSuccess(#NonNull Response<SignupResponse> response) {
}
});
Can you try this below code?. The one mistake I can figure out is implementing Callback instead of Callback<T>
public abstract class RetrofitCallback<T> implements Callback<T> {
private BaseActivity mContext;
public RetrofitCallback(Context context) {
mContext = (BaseActivity) context;
}
#Override
public void onResponse(Call call, Response response) {
mContext.hideLoading();
onSuccess(response);
}
#Override
public void onFailure(Call call, Throwable t) {
mContext.hideLoading();
}
public abstract void onSuccess(#NonNull Response<T> response);
}
I am trying to test functions from my Presenter Class. In below, I can reach getSomeThing() function however, I cannot reach the getData() and getError() functions.
Volley functions are not working in unit tests. Further help would be highly appreciated as I am struggling with this for over a week.
Below is my Presenter Class, Presenter Listener and Test Function.
my Presenter Class:
public abstract class SomePresenter implements BasePresenterListener {
private static final String sTAG = SomePresenter.class.getSimpleName();
private Context context;
private Integer testInteger;
protected SomePresenter(Context context, Integer testInteger) {
this.context = context;
this.testInteger = testInteger;
onResponse();
}
#Override
public void onResponse() {
try {
Thread.sleep(1000);
getSomeThing();
} catch (InterruptedException e) {
e.printStackTrace();
}
final GetRequest<SomeResponse> someResponseRequest =
ApiRequests.getSomeResponse(
new Response.Listener<SomeResponse>() {
#Override
public void onResponse(SomeResponse response) {
getData(response);
}
}
,
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
ErrorResponse errorResponse = new ErrorResponse();
errorResponse.setMessage(Constant.NETWORK_ERROR);
getError(errorResponse);
}
}
);
NetworkInstance.addRequest(context, poiResponseGetRequest, sTAG);
}
public static void cancelRequest(Context context) {
NetworkInstance.cancelAllRequests(context, sTAG);
}
protected abstract void getSomeThing();
protected abstract void getData(SomeResponse response);
protected abstract void getError(ErrorResponse response);
}
my BasePresenter Class:
public interface BasePresenterListener {
void onResponse();
}
my Unit Test Function:
#Test
public void test() throws InterruptedException {
new SomePresenter(mockContext, 107){
#Override
protected void getData(PoiResponse response) {
SomeLogger.debug("getData works");//this is not called.
}
#Override
protected void getSomeThing() {
SomeLogger.debug("getSomeThing works!");//this is called.
}
#Override
protected void getError(ErrorResponse response) {
SomeLogger.debug("ErrorResponse works!"); //this is not called.
}
};
}
I have looked below links none of them solved my problem.
Unit testing a network response. Works when debugging, not when actually running
Android Unit test with Volley
In my case is I can reach the getSomething() function from unit test but I cannot reach the getData() nor getError() functions because Volley does not seem to work in unit tests.
All, getSomething(), getData(), getError() functions are callback functions, I can reach the getSomeThing() function but I cannot reach the getData() and getError() functions.
I'm creating a list of Observable using a list of values, foreach value a custom Observable. I run them all using merge, but I can't detect which one triggers onNext() or onError()
Like in the code below:
List<Observable<MyHttpRsObj>> observables = new ArrayList<>();
for (String param : paramsList) {
Observable<MyHttpRsObj> objObservable = MyRestClient.get().doHttpRequest(param);
observables.add(fileUploadObservable);
}
Observable<BaseRs> combinedObservables = Observable.merge(observables);
combinedObservables.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(new Subscriber<MyHttpRsObj>() {
#Override
public void onCompleted() {
//called only once when all Observables finished
}
#Override
public void onError(Throwable throwable) {
//how to know which Observable has error (which param)
}
#Override
public void onNext(MyHttpRsObj myHttpRsObj) {
//how to know which Observable has sccess (which param)
}
});
It is impossible to know which obsevable triggered the error since you merge all observables into single one.
your best bet is to use one observer for each observable. And a last one for merged Observable.
Like this:
List<Observable<MyHttpRsObj>> observables = new ArrayList<>();
for (String param : paramsList) {
//change to connectable Observable
ConnectableObservable<MyHttpRsObj> objObservable = MyRestClient.get()
.doHttpRequest(param)
.publish();
//don't forget to connect
observable.connect();
observables.add(fileUploadObservable);
//subscribe for each observable
objObservable.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(new Subscriber<MyHttpRsObj>() {
#Override
public void onCompleted() {
//just partial completed
}
#Override
public void onError(Throwable throwable) {
//you can access param from here
}
#Override
public void onNext(MyHttpRsObj myHttpRsObj) {
//access onNext here
//you can access param from here
}
});
}
Observable<BaseRs> combinedObservables = Observable.merge(observables);
combinedObservables.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(new Subscriber<MyHttpRsObj>() {
#Override
public void onCompleted() {
//called only once when all Observables finished
}
#Override
public void onError(Throwable throwable) {
//don't handle error here
}
#Override
public void onNext(MyHttpRsObj myHttpRsObj) {
}
});
PS: use ConnectableObservable to avoid emitting twice
I have a series of asynchronous operations
private void doSomething(){
get("/something", new Callback(){
void onComplete(String data){
updateUi(something, data);
doSomethingElse();
}
});
}
private void doSomethingElse(){
get("/something/else", new Callback(){
void onComplete(String data){
updateUi(somethingElse, data);
doYetAnotherThing();
}
});
}
private void doYetAnotherThing(){
get("/yet/another/thing", new Callback(){
void onComplete(String data){
updateUi(yetAnotherThing, data);
allDone();
}
});
}
This suffers from few problems:
Cannot reuse any of the callbacks elsewhere since each is intrinsically tied to the "next step"
Re-ordering operations or inserting another operation is non-intuitive and involves jumping all over the place.
I have looked at the following options to mitigate this:
ExecuterService#invokeAll - I don't see how this solution can be used without blocking.
RxJava - I would prefer to avoid such a paradigm shift in my application if I can!
Guava's ListenableFutures and its transform method. I saw this referred to in few places around the interwebs nut I honestly don't see how this would solve my problem.
So, the question is: What would be a good pattern to chain a series of asynchronous calls in Java? Looking for a solution that works with Java 7 since I need this for an Android app.
There certainly is some guessing involved, regarding the actual intention and use-case where you encountered this problem. Additionally, it is not entirely clear what something, somethingElse and yetAnotherThing are (where they come from and where they should go).
However, based on the information that you provided, and as an addition to (or rather extension or generalization of) the answer by slartidan: The difference between these dummy calls that you sketched there seem to be
The String argument that is passed to the get method
The Callback that is called
Which method is executed next
You could factor out these parts: The String argument and the Callback could be passed as parameters to a general method that creates a Callable. The sequence of the calls could simply be defined by placing these Callable objects into a list, in the appropriate order, and execute them all with a single threaded executor service.
As you can see in the main method of this example, the sequence of calls can then be configured rather easily:
import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ChainedAsyncTest {
public static void main(String[] args) throws InterruptedException {
ChainedAsyncTest t = new ChainedAsyncTest();
ExecutorService e = Executors.newFixedThreadPool(1);
e.invokeAll(Arrays.asList(
t.call("/something", t.somethingCallback),
t.call("/something/else", t.somethingElseCallback),
t.call("/yet/another/thing", t.yetAnotherThingCallback),
t.allDone()));
}
private Callback somethingCallback = new Callback() {
#Override
public void onComplete(String data) {
updateUi("something", data);
}
};
private Callback somethingElseCallback = new Callback() {
#Override
public void onComplete(String data) {
updateUi("somethingElse", data);
}
};
private Callback yetAnotherThingCallback = new Callback() {
#Override
public void onComplete(String data) {
updateUi("yetAnotherThing", data);
}
};
private Callable<Void> call(
final String key, final Callback callback) {
return new Callable<Void>() {
#Override
public Void call() {
get(key, callback);
return null;
}
};
}
private Callable<Void> allDone() {
return new Callable<Void>() {
#Override
public Void call() {
System.out.println("allDone");
return null;
}
};
}
interface Callback
{
void onComplete(String data);
}
private void get(String string, Callback callback) {
System.out.println("Get "+string);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
callback.onComplete("result of "+string);
}
private void updateUi(String string, String data) {
System.out.println("UpdateUI of "+string+" with "+data);
}
}
(The example uses invokeAll, which blocks until all tasks have been executed. This could be solved differently to be really non-blocking at the call site. The main idea is to create a list of the tasks, which are all created by the same method call)
Spontainious thought: You could define the chained calls as a method parameter to make your methods reusable. Here is my example code:
public class Scribble {
final Callback step1 = new Callback() {
void onComplete(String string) {
doSomethingElse(step2);
};
};
final Callback step2 = new Callback() {
void onComplete(String string) {
doYetAnotherThing(step3);
};
};
final Callback step3 = new Callback() {
void onComplete(String string) {
allDone();
}
};
private void start() {
doSomething(step1);
}
private void doSomething(final Callback externalCallback) {
get("/something", new Callback() {
void onComplete(String data) {
updateUi(something, data);
externalCallback.onComplete(data);
}
});
}
private void doSomethingElse(final Callback externalCallback) {
get("/something/else", new Callback() {
void onComplete(String data) {
updateUi(somethingElse, data);
externalCallback.onComplete(data);
}
});
}
private void doYetAnotherThing(final Callback externalCallback) {
get("/yet/another/thing", new Callback() {
void onComplete(String data) {
updateUi(yetAnotherThing, data);
externalCallback.onComplete(data);
}
});
}
// - the code below is only to make everything compilable -
public class Callback {
void onComplete(String string) {
}
}
private Object something;
protected Object somethingElse;
protected Object yetAnotherThing;
protected void allDone() {
System.out.println("Scribble.allDone()");
}
protected void updateUi(Object yetAnotherThing2, String data) {
System.out.println("Scribble.updateUi()"+data);
}
private void get(String string, Callback callback) {
System.out.println("get "+string);
callback.onComplete(string);
}
public static void main(String[] args) {
new Scribble().start();
}
}
I totally support the approved answer, but I'm also tossing in something I created for these types of problems that comes in handy when you start adding conditional logic within your chain of asynchronous actions. I recently fermented this into a simple library (jasync-driver).
Here is how you'd wire up your example. As you can see, each task has no knowledge of the task that follows. In contrast to the approved answer, the chaining of the tasks is done through a simple synchronous (...looking) method body instead of a list.
public void doChainedLogic() {
final AsyncTask<Void, Void> doSomething = new AsyncTask<Void, Void>() {
#Override
public void run(Void arg, final ResultHandler<Void> resultHandler) {
get("/something", new Callback() {
public void onComplete(String data) {
updateUi(something, data);
resultHandler.reportComplete();
}
});
}
};
final AsyncTask<Void, Void> doSomethingElse = new AsyncTask<Void, Void>() {
#Override
public void run(Void arg, final ResultHandler<Void> resultHandler) {
get("/something/else", new Callback() {
public void onComplete(String data) {
updateUi(somethingElse, data);
resultHandler.reportComplete();
}
});
}
};
final AsyncTask<Void, Void> doYetAnotherThing = new AsyncTask<Void, Void>() {
#Override
public void run(Void arg, final ResultHandler<Void> resultHandler) {
get("/yet/another/thing", new Callback() {
public void onComplete(String data) {
updateUi(yetAnotherThing, data);
resultHandler.reportComplete();
}
});
}
};
// This looks synchronous, but behind the scenes JasyncDriver is
// re-executing the body and skipping items already executed.
final JasyncDriver driver = new JasyncDriver();
driver.execute(new DriverBody() {
public void run() {
driver.execute(doSomething);
driver.execute(doSomethingElse);
driver.execute(doYetAnotherThing);
}
});
}
Now here's a tweak to the example that includes some conditional logic that depends upon an asynchronous result:
final AsyncTask<Void, String> checkSomething = new AsyncTask<Void, String>() {
#Override
public void run(Void arg, final ResultHandler<String> resultHandler) {
get("/check/something", new Callback() {
public void onComplete(String data) {
resultHandler.reportComplete(data);
}
});
}
};
final JasyncDriver driver = new JasyncDriver();
driver.execute(new DriverBody() {
public void run() {
driver.execute(doSomething);
if ("foobar".equals(driver.execute(checkSomething))) {
driver.execute(doSomethingElse);
}
driver.execute(doYetAnotherThing);
}
});
As you can see, asynchronous conditional logic is as simple as writing a standard if statement.
I'm implementing a class that is responsible for all my HTTP requests from the Blackberry. I have around 10 or so screens that use this class to query a web service and get data from it. What would be the standard pattern to use in this case?
Currently I have it setup as follows -
public class NetworkAccessClass
{
public NetworkAccessClass(String url, String methodName, Vector paramNames, Vector paramValues, MainScreen screen) {
// perform inits
}
public void run() {
// Get Data
if(screen.instanceOf(LoginScreen)) {
((LoginScreen) screen).requestSucceded(responseData);
}
// So on for all 10 screens.
catch() {
((LoginScreen) screen).requestFailed(errorCode);
// So on for all 10 screens.
}
}
}
It works, but doesn't look right, and if a single screen has multiple types network requests, I'm being forced to add a flag to keep track of which function it's supposed to call back.
Is there a better way to do this?
Thanks,
Teja.
Use a callback interface, e.g. ResponseHandler:
public class NetworkAccessClass
{
public interface ResponseHandler {
void requestSucceeded(ResponseData responseData);
void requestFailed(ErrorCode errorCode);
}
public NetworkAccessClass(
String url,
String methodName,
Vector paramNames,
Vector paramValues,
ResponseHandler responseHandler) {
// perform inits
}
public void run() {
// Get Data
try {
...
responseHandler.requestSuceeded(responseData);
catch() {
responseHandler.requestFailed(errorCode);
}
}
}
This hopefully decouples your NetworkAccessClass from knowing about all the screens. Then either your screens implement NetworkAccessClass.ResponseHandler or they pass an adapter handler (anonymous inner class) to call the proper methods on the screen, e.g.
class LoginScreen {
...
new NetworkAccessClass(url, methodName, paramNames, paramValues,
new ResponseHandler() {
#Override
void requestSucceeded(ResponseData responseData) {
LoginScreen.this.handleLoginSuccess(responseData);
}
#Override
void requestFailed(ErrorCode errorCode) {
LoginScreen.this.handleLoginFailure(errorCode);
}
}
...
}
You could use a listener, which is a simple interface the network class would call back whenever something interesting happens :
public interface NetworkListener {
void requestSucceeded(byte[] responseData);
void requestFailed(int errorCode);
}
public class NetworkAccess {
// ...
public void run() {
// Get Data
if (successful) {
fireSucess(responseData);
}
catch(SomeException e) {
fireFailure(errorCode);
}
}
public void addNetworkListener(NetworkListener listener) {
// add listener to list of listeners
}
private void fireSuccess(byte[] responseData) {
for (NetworkListener l : listeners) {
l.requestSucceeded(responseData);
}
}
// ...
}
public class LoginScreen {
private void foo() {
NetworkAccess access = new NetworkAccess(...);
access.addNetworkListener(new NetworkListener() {
public void requestSucceeded(byte[] responseData) {
// do what you want
}
public void requestFailed(int errorCode) {
// do what you want
}
});
}
}
This is known as the Observable/observer pattern. The observable notifies its observers when something happens, but without having to know their exact type. The listsner class decouples the two parties.