How to POST with RxJava 2 + Retrofit 2? - android

This question may sound like a no-brainer but I'm having a hardtime.
I can do the post with retrofit 2 this way:
class RetrofitClient {
private static Retrofit retrofit = null;
static Retrofit getClient(String baseUrl) {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
Api service interface:
#POST("postsInit")
#FormUrlEncoded
Call<InitPost> postInit(
#Field("appVersion") String versionName,
#Field("appId") String applicationId,
);
And finally:
apiService.postInit(versionName, applicationId).enqueue(new Callback<InitPost>() {
#Override
public void onResponse(#NonNull Call<InitPost> call, #NonNull Response<InitPost> response) {
if (response.isSuccessful()) {
Timber.d("post submitted to API");
getInitResponse();
}
}
#Override
public void onFailure(#NonNull Call<InitPost> call, #NonNull Throwable t) {
if (call.isCanceled()) {
Timber.e("Request was aborted");
} else {
Timber.e("Unable to submit post to API.");
}
}
});
How can I convert this to RxJava 2 ? I've already implemented the converter factory but there is no info on the internet for using rxJava 2 and retrofit 2 together.

Converting your call in RxJava code:-
apiService.postInit(versionName, applicationId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.unsubscribeOn(Schedulers.io())
.subscribe(new Subscriber<InitPost>() {
#Override
public void onSubscribe(Subscription s) {
}
#Override
public void onNext(InitPost initPost) {
}
#Override
public void onError(Throwable t) {
}
#Override
public void onComplete() {
}
});
}
Post service interface:
#POST("postsInit")
#FormUrlEncoded
Observable<InitPost> postInit(
#Field("appVersion") String versionName,
#Field("appId") String applicationId,
);

Related

Null Response fron "http" API using retrofit

I'm using retrofit to connect APIs. It is working fine when fetching data from https API but getting response "Null" and error body response "okhttp3.ResponseBody$1#174390c" when fetching data from http API.
Here is the Retrofit client class:
public static Retrofit getSClient(String baseUrl) {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(ScalarsConverterFactory.create())
.build();
}
return retrofit;
}
Here is the Apiservice Class:
#GET("Mobile/OperatorFetch?")
Call<String>getOperatorDetails(#Query("apimember_id")String apiMemberId,
#Query("api_password")String apiPassword,
#Query("Mobileno")String mobileNumber);
Here is the ApiUtils Class:
public static ApiService getSApiService(){
return RetrofitClient.getSClient(PLAN_URL).create(ApiService.class);
}
Here is my network request method from Repository class:
private void fetchOperator(String apiId, String apiPassword, String mobile) {
ApiService apiService = ApiUtills.getSApiService();
apiService.getOperatorDetails(apiId, apiPassword, mobile)
.enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
if (response.isSuccessful() && response.body() != null){
Log.e(TAG,"Operator fetch successful: " + response.body().toString());
}else {
Log.e(TAG,"Operator fetch failed: " + response.errorBody().toString());
}
}
#Override
public void onFailure(Call<String> call, Throwable t) {
Log.e(TAG,"Fetch operator failed" + t.getMessage());
}
});
}
Getting response from Post Man

Android - Retrofit does not display data

I'm trying to learn Retrofit making simple weather app and I have some problem. I made two methods to display data in Activity and method does not work outside onCreate, but second one in works. In Android Profiler I can see JSON logs, but still I don't see anything in Activity. What's the problem?
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(WeatherAPI_Interface.API_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
WeatherAPI_Interface weatherAPIInterface = retrofit.create(WeatherAPI_Interface.class);
latitude = 37.8267;
longitude = -122.4233;
Call<Currently> call = weatherAPIInterface.getWeather(latitude, longitude);
call.enqueue(new Callback<Currently>() {
#Override
public void onResponse(#NonNull Call<Currently> call, #NonNull Response<Currently> response) {
temp_textview.setText(String.valueOf(response.body().getCurrently().getTemperature()));
city_textview.setText(response.body().getTimezone());
image_View.setImageResource(Integer.parseInt(response.body().getCurrently().getIcon()));
}
#Override
public void onFailure(#NonNull Call<Currently> call, #NonNull Throwable t) {
}
});
}
#Override
public void getCurrentWeather(final Currently currently) {
latitude = 37.8267;
longitude = -122.4233;
NetworkClient.getInstance().getWeather(latitude, longitude).enqueue(new Callback<Currently>() {
#Override
public void onResponse(#NonNull Call<Currently> call, #NonNull Response<Currently> response) {
weather_textview.setText((CharSequence) response.body().getCurrently().getSummary());
pressure_textview.setText((CharSequence) response.body().getDaily().getData());
temp_textview.setText(String.valueOf(currently.getCurrently().getTemperature()));
Log.d(TAG, "City" + currently.getLatitude());
}
#Override
public void onFailure(Call<Currently> call, Throwable t) {
Log.d(TAG, "Failed" + t.getMessage());
}
});
}
public class NetworkClient {
private static WeatherAPI_Interface service;
public static WeatherAPI_Interface getInstance() {
if (service == null) {
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(WeatherAPI_Interface.API_URL)
.build();
service = retrofit.create(WeatherAPI_Interface.class);
return service;
}
else {
return service;
}
}
}
You didn't call the function how can it work?
when the activity starts it'll run the code in OnCreate ( and any call in it) only, so to run any function outside it you need to call it.

Reusing Retrofit method

I have a method that makes a call to my server using Retrofit:
public class MainActivity extends AppCompatActivity {
// ... activity methods here, removed for simplicity ...
// Used to subscribe to a user given their userId
public void subscribeToUser(int userId) {
final ApiInterface apiService = ApiClient.createService(ApiInterface.class);
Call<BasicResponse> call = apiService.subscribe(userId);
call.enqueue(new Callback<BasicResponse>() {
#Override
public void onResponse(Call<BasicResponse> call, Response<BasicResponse> response) {
if (response.isSuccessful()) {
Toast.makeText(MainActivity.this, "Success", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(MainActivity.this, "Failed", Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(Call<BasicResponse> call, Throwable t) {
Log.e(TAG, t.toString());
}
});
}
}
I now need to use this same method (subscribeToUser()) in another activity, but it doesn't make sense to copy and paste the method into the other activity. Then I would just have the same code twice.
So can I put the method into one place and have it let the activities know whether or not the call succeeded or failed? How should I organize this?
Here is my ApiClient.java class:
public class ApiClient {
public static final String API_BASE_URL = "http://www.website.com/api/";
private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
private static Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create());
public static <S> S createService(Class<S> serviceClass) {
Retrofit retrofit = builder.client(httpClient.build()).build();
return retrofit.create(serviceClass);
}
public static <S> S createService(Class<S> serviceClass, final String authToken) {
if (authToken != null) {
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request original = chain.request();
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder()
.header("Authorization", "Bearer " + authToken)
.method(original.method(), original.body());
Request request = requestBuilder.build();
return chain.proceed(request);
}
});
}
OkHttpClient client = httpClient.build();
Retrofit retrofit = builder.client(client).build();
return retrofit.create(serviceClass);
}
}
And here is my ApiInterface.java class:
public interface ApiInterface {
#FormUrlEncoded
#POST("subscribe")
Call<BasicResponse> subscribe(#Field("userId") Integer userId);
}
Thanks.
In my opinion, createService(ApiInterface.class) shouldn't be invoked multiple times. It's not necessary and slows down your application. You can try to create UserService with singleton pattern as below:
public class UserService {
private UserService userService;
final ApiInterface apiService;
//Contructor private to prevent init object from outside directly.
private UserService() {
apiService = ApiClient.createService(ApiInterface.class);
}
//use this method when you need to use UserService
public static UserService getInstance() {
if(userService == null) {
userService = new UserService();
}
}
// Used to subscribe to a user given their userId
public void subscribeToUser(int userId, ServiceCallBack serviceCallBack) {
final ApiInterface apiService = ApiClient.createService(ApiInterface.class);
Call<BasicResponse> call = apiService.subscribe(userId);
call.enqueue(new Callback<BasicResponse>() {
#Override
public void onResponse(Call<BasicResponse> call, Response<BasicResponse> response) {
if (response.isSuccessful()) {
Toast.makeText(MainActivity.this, "Success", Toast.LENGTH_LONG).show();
serviceCallBack.successful(response);
} else {
Toast.makeText(MainActivity.this, "Failed", Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(Call<BasicResponse> call, Throwable t) {
Log.e(TAG, t.toString());
serviceCallBack.fail(t);
}
});
}
//this is callback interface, help you know whether success from outside.
interface ServiceCallBack {
void successful(Response response);
void fail(Throwable t);
}
}
How to use:
UserService.getInstance(1, new ServiceCallBack(){
#Override
public void successful(Response response) {
//process successful
}
#Override
public void fail(Throwable t) {
//process fail
}
});
Now you can put all methods relate to User api to UserService class to reuse.

How to get Header from RxAndroid Response.?

This is the function which i used for the network calls.
private void generateNewCard()
{
showProgressDialog();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(NetworkCalls.BASE_URL)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
NetworkCalls.CustomerApi customerApi = retrofit.create(NetworkCalls.CustomerApi.class);
customerApi.addExistingCard(prefs.getString(Constants.AUTH_TOKEN, ""), "", CREATE_NEW_CARD)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<DataGeneral>() {
#Override
public void onCompleted() {
stopProgressDialog();
Log.d(TAG, "onCompleted DataGeneral" + DataGeneral.class);
}
#Override
public void onError(Throwable e) {
Log.d(TAG, "onError" + e.getMessage());
stopProgressDialog();
}
#Override
public void onNext(DataGeneral data) {
stopProgressDialog();
if (data.getStatus() == 1) {
}
}
});
}
and the interface class is here,
#FormUrlEncoded
#POST("add-loyalty-card")
Observable<DataGeneral> addExistingCard(#Field("Token") String token, #Field("cardHas") String cardHas, #Field("ltyCardId") String ltyCardId);
This works fine for me. I am getting desired result. I wish to know how can i get the Header from the response and is there a way to simplify the above code?
Any help would be really appreciated.

Error: No Retrofit annotation found. (parameter #2)

I have this Interface:
public interface InterfazAguaHttp {
#FormUrlEncoded
#POST("/")
Call<String> saveContador(#Field("contador") Long contador, Callback<String> callBack);
}
The rest of the code is this:
Retrofit builder = new Retrofit.Builder()
.baseUrl(ValoresGlobales.urlServlet)
.addConverterFactory(GsonConverterFactory.create())
.build();
InterfazAguaHttp interfaz = builder.create(InterfazAguaHttp.class);
Call<String> respuesta = interfaz.saveContador(93847597L, new Callback<String>() {
#Override
public void onResponse(Response<String> response, Retrofit retrofit) {
//Some logging
}
#Override
public void onFailure(Throwable t) {
//Some logging
}
});
This is all inside a try-catch block. In the catch, I am receiving this error:
Error: No Retrofit annotation found. (parameter #2) for method InterfazAguaHttp.saveContador
How could I get rid of this error, and still have my callback?
Thank you.
change your interface method to this
public interface InterfazAguaHttp {
#FormUrlEncoded
#POST("/")
Call<String> saveContador(#Field("contador") Long contador);
}
and the rest of the code like this
Retrofit builder = new Retrofit.Builder()
.baseUrl(ValoresGlobales.urlServlet)
.addConverterFactory(GsonConverterFactory.create())
.build();
InterfazAguaHttp interfaz = builder.create(InterfazAguaHttp.class);
Call<String> respuesta = interfaz.saveContador(93847597L);
respuesta.enqueue(new Callback<String>() {
#Override
public void onResponse(Response<String> response, Retrofit retrofit) {
//Some logging
}
#Override
public void onFailure(Throwable t) {
//Some logging
}
});
Link for reference

Categories

Resources