should i put my retrofit calls inside and Android Service class?
for my application iam calling retrofit inside in some classes for example like below
Call<ArrayList<CantItem>> mycall = retrofitcalls.getCanteenItems("url.php", urldatamap);
mycall.enqueue(new Callback<ArrayList<CantItem>>() {
#Override
public void onResponse(Response<ArrayList<CantItem>> response, Retrofit retrofit) {
int code = response.code();
Log.d("code ", String.valueOf(code));
if (code == 200 || code == 201) {
ArrayList<CantItem> cantitems = response.body();
Log.d("retrieved", "returned items");
savedToSharedPrefs(createString(cantitems));
cantmap = createMap(cantitems);
presenter.updateView(cantmap);
}
}
#Override
public void onFailure(Throwable t) {
Log.d("couldnt retrieve", "failure");
}
});
I was wondering should i put this call inside an Android Service class? as my retrofit call runs asynchronously anyway? Every tutorial ive seen seems to run it in either classes or activities. I haven't seen anyone using a service. Im not 100% sure what the best approach is at present. thanks
It really depends on your requirements. Do you need the result of the webservice call even if your application killed?
If yes, then put it into a service.
If not then just starts something from your Activity.
Related
I have developed an android application where I need to fetch a list using rest API call and show on my application. The list gets updated frequently. I have written the following code using RxAndroid and retrofit to make the api call :
private void fetchAllData() {
disposable.add(Observable.interval(0,60,TimeUnit.SECONDS).
subscribeOn(Schedulers.io()).
flatMap(i -> apiService.getData(fetchActiveData)).
observeOn(AndroidSchedulers.mainThread()).
subscribeWith(new DisposableObserver<DataResponse>() {
#Override
public void onNext(DataResponse dataResponse) {
Log.i(TAG, "The rest api was called again");
List<Data> dataList = dataResponse.getData();
displayData(dataList,false);
}
#Override
public void onError(Throwable e) {
Log.e(TAG, "The exception is thrown :: " + e.getMessage());
displayData(null,true);
fetchAllData();
}
#Override
public void onComplete() {
}
})
);
}
Using above code , I am able to make api call every 60 seconds and update my list. If there is any new item which I am not displaying on the application , then for that i have the logic to show the notification.
To enhance my application , I need to make the api call when the application is closed and not running on background. Can someone please suggest me how do I achieve this with RxJava.
I want to send a String message to database when user presses a specific button in the LibGDX game I am designing for android. How do I go about doing that? Following is the code I tried. But it does not work.
Net.HttpRequest httpRequest = new Net.HttpRequest();
httpRequest.setMethod("POST");
httpRequest.setUrl("URL is here");
httpRequest.setContent("INSERT INTO `game_table` (`Button`) VALUES ('Button 1 Pressed')");
Net.HttpResponseListener httpResponseListener = new Net.HttpResponseListener() {
#Override
public void handleHttpResponse(Net.HttpResponse httpResponse) {
Gdx.app.log("Log httpResponse", httpResponse.getResultAsString());
}
#Override
public void failed(Throwable t) {
}
#Override
public void cancelled() {
}
};
Gdx.net.sendHttpRequest(httpRequest,httpResponseListener);
Log does not provide anything in android monitor. I also tried using AsyncTask and without AsyncTask to implement this code. But neither works.
Am I missing something? If so could you give me small code snippet that will work?
You don't need to use an AsyncTask, libGDX' HTTPRequest is async out of the box.
You did not log anything if the request fails or is cancelled so probably that's the case.
Here is my current code. The problem with this code is I need to wait get the data sequentially. The loading time is poor because of this. I want to use something like .enqueue() to get asynchronously several data at once, but I want to wait until I get all the data before continuing the process. Is it possible to do it with Retrofit?
List<Data> datas = new ArrayList<>();
for (long dataId : mDataIds) {
Response<T> response = resource.getData(dataId).execute();
if (response.isSuccessful()) {
datas.add(data.body());
}
}
//do something else
You can solve this problem very elegantly using RxJava.
If you never heard of RxJava before, it is a solution to many of your problems.
If you don't use java8 or retrolambda I recommend you to start using it, as it makes working with RxJava a piece of cake.
Anyway here's what you need to do:
// 1. Stream each value from mDataIds
Observable.from(mDataIds)
// 2. Create a network request for each of the data ids
.flatMap(dataId -> resource.getData(dataId))
// 3. Collect responses to list
.toList()
// Your data is ready
.subscribe(datas -> {}, throwable -> {});
1) First add RxJava2 dependencies to your project
2) Define retrofit api interface methods which return RxJava observable types
public interface DataApi {
#GET("dataById/")
Observable<Data> getData(#Query("id") String id);
}
3) Call api passing input data like below.
Observable.fromIterable(idList).subscribeOn(Schedulers.computation())
.flatMap(id -> {
return retrofitService.getData(id).subscribeOn(Schedulers.io());
}).toList().
.observeOn(AndroidSchedulers.mainThread()).subscribe( listOfData -> {// do further processing }, error -> { //print errors} );
For reference : http://www.zoftino.com/retrofit-rxjava-android-example
Define interface with callback Model type.
public interface LoginService {
#GET("/login")
Call<List<Login>> getLogin();
}
In you calling method override the callback method.
LoginService loginService = ServiceGenerator.createService(LoginService.class);
Call<List<Login>> call = loginService.getLogin();
call.enqueue(new Callback<List<Login>>() {
#Override
public void onResponse(Call<List<Login>> call, Response<List<Login>> response) {
if (response.isSuccessful()) {
// Login successful
} else {
// error response, no access to resource?
}
}
#Override
public void onFailure(Call<List<Login>> call, Throwable t) {
// something went completely south (like no internet connection)
Log.d("Error", t.getMessage());
}
}
I would recommend using RxJava and try it. You have something called FlatMap to combine the results.
To Start here is the tutorial start for RxJava2 and Retrofit2.
I'm making a network request inside a Repository class in my Android app. I'm doing this for learning purposes, so I'm trying to understand, without using RXJava, how would I update the UI all the way from my Repository?
The trail of calls goes like so MainActivity -> Presenter -> Interactor -> Repository -> Network
And here is my code in the repository
WeatherRepository {
WeatherNetwork network = new WeatherNetwork();
public CurrentWeather getCurrentWeather(float lat, float lng) {
network.getDailyWeather(lat, lng, new Callback() {
#Override
public void onFailure(Request request, IOException e) {
}
#Override
public void onResponse(Response response) throws IOException {
try{
String jsonData = response.body().string();
if (response.isSuccessful()) {
CurrentWeather currentWeather = getCurrentWeatherData(jsonData);
}
} catch(JSONException e) {
Log.d("DWPresen" + " JSONEXCEPTION", e.getMessage());
} catch(IOException e){
Log.d("DWPresent" + " IOEXCEPTION", e.getMessage());
}
}
});
}
}
Imho there are two classical ways to do such a thing:
One way would be to pass a callback object down to the repository and call the callback action when you get your response.
The second (and imho more elegant) way would be to use local broadcasts in your app. They can be used to transfer messages (like if something happened in your service and you want to notify other threads - like the UI thread - about it.)
There are quite a lot of tutorials about (local) broadcasts in android. Normal broadcasts are used to communicate between apps (and between the system and an app), while local broadcasts can be used to just send information within your app.
There is a library called EventBus that works very well with MVP structure.
Briefly, it passes the event(an object with data) from one class to another. In your case, you can pass an event with CurrentWeather object inside of it from Repository to Presenter and then update UI.
I'm working on an Android App. I'm using Retrofit to manage the http request to the server-side endpoints. Currently when I'm doing a request I'm doing something like this:
Observable<List<ApiFeedResponse>> feedObservable = mFeedRepository.getFeed(0, 50)
.flatMap(apiFeedsResponse -> {
if (apiFeedsResponse.code() != 200) {
if (apiFeedsResponse.code() == 304) {
List<ApiFeedResponse> body = apiFeedsResponse.body();
return Observable.just(body);
} else {
return Observable.error(new ServerSideErrorException(apiFeedsResponse));
}
} else {
return Observable.just(apiFeedsResponse.body());
}
});
My FeedRepository calls the Retrofit service. I've an endpoint that is like myhost.com/rest/userfeed?page=0&pageSize=50. The thing is that I'm also using etags to get cached server-side responses. And I want to be able to differentiate between a normal 200 http response and a "not modified" 304 response. I want to extend the rx.Subscriber lifecycle methods (onNext, onError and onComplete) to be something like (onSuccess, onServerError, onNotModified, onServerResult). That way when I subscribe to this methods is going to look like this:
getFeed(0, 50).subscribe(new ServerSubscriber<List<Feed>>() {
//Executed when the response is 200
#Override
protected void onSuccess(List<Feed> feed) {
}
//Executed when the response is 304
#Override
protected void onNotModified(List<Feed> feed) {
}
//Executed if something goes wrong while doing the http request (code is different than 200 or 304)
#Override
protected void onServerSideError(ServerSideErrorException e) {
}
//Executed always that the result of the http request is successfull (200 or 304)
#Override
protected void onServerResult(List<Feed> feed) {
}
});
I have been looking through different repos trying to find if someone has done something similar and the closes thing that I found was this: https://github.com/ReactiveX/RxJava/issues/1034
But I still can't fully understand how to implement custom rx.Observables and custom rx.Subscribers. Any advice is welcome.
Why not repackage your logic in a reusable form?
public <T> Transformer<Response<T>, T> applyCache(
Supplier<T> src,
Consumer<Response<T>> sink) {
return responseSrc -> responseSrc.flatMap(response -> {
switch(response.code()) {
case 200:
sink.accept(response);
return Observable.just(apiFeedsResponse.body());
case 304:
return Observable.just(src.get());
default:
return Observable.error(new ServerSideErrorException(apiFeedsResponse));
}
}
Just add the cache get/set functions (and adjust to taste); use like:
mFeedRepository
.getFeed(0, 50)
.compose(applyCache(feedCache::get, feedCache::set)
I think the solutions to your problems can be fixed in Retrofit/OkHttp.
Retrofit2 uses OkHttp3 under the hood to execute the API calls. OkHttp can handle the 304 not modified status code and deliver you the result from cache. To do that you need to set up retrofit to use a custom OkHttp client with cache.
For more custom callbacks there the solution is custom CallAdapter. There is an example for that in the retrofit repo which looks similar to yours. RxJava already uses a call adapter, maybe you can base is on that.