How can i get Realtime Data from API using Retrofit android - android

Hello Guys I am trying to realtime get data when change data in API automatic referesh my layout and updated data show it. How can i do that?
Here is my Code :-
I use this Dependencies :-
// retrofit, gson
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.squareup.retrofit2:retrofit:2.6.1'
implementation 'com.squareup.retrofit2:converter-gson:2.6.1'
Here is my API interface method :-
#GET("get_doctor_expense_categories.php")
Call<GetExpenseCategoriesListResponse> get_doctor_expense_categories(#Query("doctor_id") String doctor_id);
And this my ApiClient :-
public class ApiClient {
private static final String ROOT_URL = "YOUR URL";
public static ApiInterface getApiService() {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(1, TimeUnit.MINUTES)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS)
.build();
Gson gson = new GsonBuilder().setLenient().create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ROOT_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
return retrofit.create(ApiInterface.class);
}
}
And This is my API call Method Where i get Data into List :-
private void getCategories(String doctor_id) {
progressDialog = CustomProgressBar.createProgressDialog(ViewCategoriesActivity.this);
final ApiInterface api = ApiClient.getApiService();
Call<GetExpenseCategoriesListResponse> call = api.get_doctor_expense_categories(doctor_id);
call.enqueue(new Callback<GetExpenseCategoriesListResponse>() {
#SuppressLint("SetTextI18n")
#Override
public void onResponse(#NonNull Call<GetExpenseCategoriesListResponse> call, #NonNull Response<GetExpenseCategoriesListResponse> response) {
if (response.code() == 200) {
progressDialog.dismiss();
if (response.body() != null) {
if (response.body().getStatus().equalsIgnoreCase("success")) {
expanseCatList = response.body().getData();
if (expanseCatList.isEmpty()) {
txt_no_data_found.setVisibility(View.VISIBLE);
recyclerView.setVisibility(View.GONE);
} else {
txt_no_data_found.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
expanseCatListAdapter = new CategoriesListAdapter(expanseCatList, ViewCategoriesActivity.this, ViewCategoriesActivity.this::catClick);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(ViewCategoriesActivity.this, LinearLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(expanseCatListAdapter);
}
} else {
Toast.makeText(ViewCategoriesActivity.this, "" + response.body().getMessage(), Toast.LENGTH_SHORT).show();
}
}
} else if (response.code() == 400) {
progressDialog.dismiss();
Toast.makeText(ViewCategoriesActivity.this, "Bad Request", Toast.LENGTH_SHORT).show();
} else if (response.code() == 401) {
progressDialog.dismiss();
Toast.makeText(ViewCategoriesActivity.this, "Unauthorized User", Toast.LENGTH_SHORT).show();
} else if (response.code() == 404) {
progressDialog.dismiss();
Toast.makeText(ViewCategoriesActivity.this, "Not Found", Toast.LENGTH_SHORT).show();
} else if (response.code() == 500) {
progressDialog.dismiss();
Toast.makeText(ViewCategoriesActivity.this, "Internal Server Error", Toast.LENGTH_SHORT).show();
} else {
progressDialog.dismiss();
Toast.makeText(ViewCategoriesActivity.this, "Unknown Error", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<GetExpenseCategoriesListResponse> call, Throwable t) {
progressDialog.dismiss();
Toast.makeText(ViewCategoriesActivity.this, "onFailer: " + t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}

This is not possible using retrofit if you want real time data you can use soup/socket

This is my retrofit setup.
public interface ApiInterface {
#GET("place/autocomplete/json?")
Call<ResponseBody> doPlaces(#QueryMap Map<String, String> options);}
public class RetrofitClient {
public static final String BASE_URL = Environment.getBaseUrl();
public static ApiInterface service (Context context) {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
.connectTimeout(3, TimeUnit.MINUTES)
.readTimeout(3, TimeUnit.MINUTES)
.writeTimeout(3, TimeUnit.MINUTES)
.addInterceptor(logging)
.addInterceptor(new NetworkConnection(context))
.addInterceptor(new ResponseStatus(context))
.build();
ApiInterface service = new Retrofit.Builder()
.baseUrl(BASE_URL).client(okHttpClient)
.build().create(UrlServices.class);
return service;
}
public static void getContentData(final Dialog dialog, final Call<ResponseBody> method, final WebResponse webResponse) {
if (dialog != null)
AppProgressDialog.show(dialog);
method.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (dialog != null)
AppProgressDialog.hide(dialog);
JsonUtil.handleResponse(response, webResponse);
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable throwable) {
if (dialog != null)
AppProgressDialog.hide(dialog);
webResponse.onResponseFailed(throwable.getMessage());
}
});
}
}
public interface WebResponse {
void onResponseSuccess(Response<ResponseBody> result);
void onResponseFailed(String error);
}
Use in Activity/Fragment
RetrofitClient.getContentData(new Dialog(context), RetrofitClient.service(context).doPlaces(hashMap), new WebResponse() {
#Override
public void onResponseSuccess(Response<ResponseBody> result) {
}
#Override
public void onResponseFailed(String error) {
}
});

Related

Data is loaded from server but isn't added to arraylist

I have the following situation: my program downloads data from server and after adds it to ArrayList.
static List<Film> generateFilms(){
Log.i(Tag, "In generate films");
List <Film> films = new ArrayList<>();
String BaseUrl = "http://www.omdbapi.com/";
Retrofit.Builder builder = new Retrofit.Builder().baseUrl(BaseUrl)
.addConverterFactory(GsonConverterFactory.create());
OkHttpClient.Builder httpClient = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS);
httpClient.addInterceptor(chain -> {
Request original = chain.request();
Request.Builder requestBuilder = original.newBuilder()
.header("Authorization", "auth-value");
Request request = requestBuilder.build();
return chain.proceed(request);
});
Retrofit retrofit = builder.build();
APIService apiService = retrofit.create(APIService.class);
final Call<Film> filmsCall = apiService.getFilms();
filmsCall.enqueue(new Callback<Film>() {
#Override
public void onResponse(#NonNull Call<Film> call, #NonNull Response<Film> response) {
if (response.isSuccessful()){
Film film = response.body();
films.add(film);
Log.i(Tag, "Response: "+Objects.requireNonNull(response.body()).getTitle());
}
else {
Log.i(Tag, "Response code: "+response.code());
}
}
#Override
public void onFailure(#NonNull Call<Film> call, #NonNull Throwable t) {
Log.i(getClass().getSimpleName(), "Error: "+t);
}
});
Log.i(Tag, "Size = "+films.size());
return films;
}
But it does it in a strange manner: it firstly returns an array and then gets the data (as I see from logs). Here's the logs:
2019-04-01 22:00:06.766 4974-4974/asus.example.com.exercise5 I/DataUtil: In generate films
2019-04-01 22:00:06.889 4974-4974/asus.example.com.exercise5 I/DataUtil: Size = 0
2019-04-01 22:00:07.367 4974-4974/asus.example.com.exercise5 I/DataUtil: Response: Batman
So, how can I solve this problem, as I need to get data firstly and then return the array?
Call<T>.enqueu() acts in asynchronous way, so you can't return data from generateFilms method itself but only make all required actions in onResponse or create custom callback.
Sample:
interface OnLoaded {
void onLoaded(Film film);
}
void generateFilms(OnLoaded callback) {
...
filmsCall.enqueue(new Callback<Film>() {
#Override
public void onResponse(#NonNull Call<Film> call, #NonNull Response<Film> response) {
if (response.isSuccessful()){
Film film = response.body();
mFilms.add(film);
Log.i(Tag, "Response: "+Objects.requireNonNull(response.body()).getTitle());
callback.onLoaded(film);
}
else {
Log.i(Tag, "Response code: "+response.code());
}
}
And use it:
private List<Film> mFilms = new ArrayList<Film>(); // class-level field
generateFilms(new OnLoaded() {
#Override
public void onLoaded(Film film) {
mFilms.add(film);
// do actions with film or mFilms if you need
}
}

Android retrofit response body, jwt in response, how do to get it?

I am using android as my front-end application and Spring boot as server part. I am using android retrofit library to connect with server.
When user logs onto server, he gets response like this.
So how do I extract "accessToken" and "tokenType" from body response?
Here is my login method in android:
private void login(LoginRequest loginRequest) {
OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
okHttpClientBuilder.addInterceptor(logging);
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClientBuilder.build());
Retrofit retrofit = builder.build();
RestAPI client = retrofit.create(RestAPI.class);
Call<LoginRequest> call = client.signIn(loginRequest);
call.enqueue(new Callback<LoginRequest>() {
#Override
public void onResponse(Call<LoginRequest> call, Response<LoginRequest> response) {
if (response.code() == 200) {
Toast.makeText(getApplicationContext(), response.body().toString(),
Toast.LENGTH_LONG).show();
Intent i = new Intent(LoginActivity.this, PostsActivity.class);
//response.body should be somewhere here
startActivity(i);
}else{
Toast.makeText(getApplicationContext(), "Uneti podaci nisu dobri",
Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(Call<LoginRequest> call, Throwable t) {
}
});
}
This is my LoginRequest class
public class LoginRequest {
private String username;
private String password;
public LoginRequest(String username, String password) {
this.username = username;
this.password = password;
}
}
Create model class for response like below
public class Token {
#SerializedName("tokenType")
private String tokenType;
#SerializedName("accessToken")
private String accessToken;
public String getTokenType() {
return tokenType;
}
public void setTokenType(String tokenType) {
this.tokenType = tokenType;
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
}
Then change the Api return type to Call<Token>
Accordingly you also need to modify the call
call.enqueue(new Callback<Token>() {
#Override
public void onResponse(Call<Token> call, Response<Token> response) {
if(response.isSuccessful()) {
Token token = response.body();
}
}
#Override
public void onFailure(Call<Token> call, Throwable t) {
}
});

how to make generic retrofit library for api calling

i'm working on API integration. i want to make generic class for API integration. which can comfortable with for all API integration.right now i'm using separate code for all API. i'm new in android application development. so please guide me.
public void getHomeCategoryDetailApi(Context context) {
final ProgressDialog loadingDialog = ProgressDialog.show(context, "Please wait", "Loading...");
Retrofit restAdapter = ApiLists.retrofit;
ApiLists apiCall = restAdapter.create(ApiLists.class);
Call<HomeCategoryModelClass> call = apiCall.homePageCatListAPI();
Log.d(TAG, "CategoryDetail : " + call.request()+" \n"+apiCall.homePageCatListAPI().toString());
call.enqueue(new Callback<HomeCategoryModelClass>() {
#Override
public void onResponse(Call<HomeCategoryModelClass> call, Response<HomeCategoryModelClass> response) {
Log.d(TAG, "onResponse: CategoryDetail:" + response.body());
Log.d(TAG, "onResponse: response.code():" + response.code());
if (response.body() == null) {
loadingDialog.dismiss();
globalClass.showAlertDialog(getActivity(), getString(R.string.InternetAlert), getString(R.string.InternetMessage), false);
} else {
loadingDialog.dismiss();
if (response.body().getStatusCode().equalsIgnoreCase("1")) {
homeCategoryImageMenu = (ArrayList<Menu>) response.body().getMenu();
thirdHorizontalRecyclerAdapter.notifyDataSetChanged();
} else {
globalClass.showAlertDialog(getActivity(), "Alert", "" + response.body().getStatus(), false);
}
}
if (response.errorBody() != null) {
try {
Log.d(TAG, "onResponse: response.errorBody()===>" + response.errorBody().string());
if (loadingDialog.isShowing() && loadingDialog != null) {
loadingDialog.dismiss();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void onFailure(Call<HomeCategoryModelClass> result, Throwable t) {
Log.d(TAG, "onFailure: " + result.toString());
loadingDialog.dismiss();
globalClass.showAlertDialog(getActivity(), getString(R.string.InternetAlert), getString(R.string.InternetMessage), false);
}
});
}
Here is Bast Way to call API
public class APIResponse {
private static String TAG = APIResponse.class.getSimpleName();
public static <T> void callRetrofit(Call<T> call, final String strApiName, Context context, final ApiListener apiListener) {
final ProgressDialog progressDialog = new ProgressDialog(context);
progressDialog.setMessage("Loading...");
progressDialog.setCancelable(false);
progressDialog.show();
call.enqueue(new Callback<T>() {
#Override
public void onResponse(Call<T> call, Response<T> response) {
if (strApiName.equalsIgnoreCase("LoginApi")) {
if (response.isSuccessful()) {
Log.d(TAG, "onResponse: " + response.body().toString());
// NearByNurse nearByNurse = (NearByNurse) response.body(); // use the user object for the other fields
// apiListener.success(url,nearByNurse);
progressDialog.dismiss();
} else {
try {
Log.d(TAG, "onResponse: " + response.errorBody().string());
apiListener.error(strApiName, response.errorBody().string());
progressDialog.dismiss();
} catch (IOException e) {
e.printStackTrace();
}
}
} else if (strApiName.equalsIgnoreCase("")) {
//Patient user = (Patient) response.body();
}
}
#Override
public void onFailure(Call<T> call, Throwable t) {
Log.d(TAG, "onFailure: " + t.toString());
if (strApiName.equalsIgnoreCase("searchNearbyTest")) {
apiListener.failure(strApiName, t.toString());
}
progressDialog.dismiss();
}
});
}
In API Calling Side
private void loginApi() {
Retrofit retrofit = ApiLists.retrofit;
ApiLists apiList = retrofit.create(ApiLists.class);
Call<JsonElement> loginApiCall = apiList.loginApi("kjdf", "fkldngdkl", "lkfdxngl", "kjngn", "jksdgkj");
APIResponse.callRetrofit(loginApiCall, "LoginApi", LoginActivity.this, this);
}
#Override
public void success(String strApiName, Object response) {
if (strApiName.equals("LoginApi")) {
}
}
#Override
public void error(String strApiName, String error) {
if (strApiName.equals("LoginApi")) {
}
}
#Override
public void failure(String strApiName, String message) {
if (strApiName.equals("LoginApi")) {
}
and interface call on API response.
public interface ApiListener {
void success(String strApiName, Object response);
void error(String strApiName, String error);
void failure(String strApiName, String message);
}
This's my common function basic call Api.java
public class Api {
private void basicCall(Call<DataResponse> call) {
if (call == null) {
listener.onResponseCompleted(Config.STATUS_404, "404 not found", null);
return;
}
call.enqueue(new Callback<DataResponse>() {
#Override
public void onResponse(#NonNull Call<DataResponse> call, #NonNull Response<DataResponse> response) {
int code = response.code();
//Check http ok
if (code == HttpURLConnection.HTTP_OK) {
//Check status
if (response.body().getStatus() == Config.STATUS_OK) {
//Everything's OK
listener.onResponseCompleted(Config.STATUS_OK, response.body().getError(), response.body().getData());
} else {
listener.onResponseCompleted(Config.STATUS_FAILED, response.body().getError(), null);
}
} else if (code == HttpURLConnection.HTTP_UNAUTHORIZED) {
try {
ErrorResponse error = Api.gson.fromJson(response.errorBody().string(), ErrorResponse.class);
listener.onResponseCompleted(Config.STATUS_401, error.getError(), error.getData());
} catch (IOException e) {
e.printStackTrace();
}
} else {
listener.onResponseCompleted(Config.STATUS_404, "404 not found", null);
}
}
#Override
public void onFailure(#NonNull Call<DataResponse> call, #NonNull Throwable t) {
listener.onResponseCompleted(Config.STATUS_404, "404 not found", null);
}
});
}
//And you can use
public void getProductList(OnResponseCompleted listener) {
this.listener = listener;
Call<DataResponse> call = apiService.getProductList();
basicCall(call);
}
}
//or orther function
This's ApiService.java
public interface ApiInterface {
#POST("product/list")
Call<DataResponse> getProductList();
}
This's OnResponseCompleted.java
public interface OnResponseCompleted {
void onResponseCompleted(int status, String error, Object data);
}
i want to make like this .i just pass some require parameter....
public void showAlertDialog(Context context, String title, String message,
Boolean status) {
AlertDialog alertDialog = new AlertDialog.Builder(context).create();
alertDialog.setTitle(title);
// Set Dialog Message
alertDialog.setMessage(message);
alertDialog.setCancelable(false);
if (status != null)
// Set alert dialog icon
alertDialog.setIcon((status) ? R.drawable.ic_success : R.drawable.ic_fail);
// Set OK Button
alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
});
// Show Alert Message
alertDialog.show();
}
Try this code..
In this code Retrofit object set up done in one class and all api calling into interface..
public class ApiClient {
private final static String BASE_URL = "https://api.github.com";
public static ApiClient apiClient;
private Retrofit retrofit = null;
public static ApiClient getInstance() {
if (apiClient == null) {
apiClient = new ApiClient();
}
return apiClient;
}
//private static Retrofit storeRetrofit = null;
public Retrofit getClient() {
return getClient(null);
}
private Retrofit getClient(final Context context) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder client = new OkHttpClient.Builder();
client.readTimeout(60, TimeUnit.SECONDS);
client.writeTimeout(60, TimeUnit.SECONDS);
client.connectTimeout(60, TimeUnit.SECONDS);
client.addInterceptor(interceptor);
client.addInterceptor(new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
return chain.proceed(request);
}
});
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client.build())
.addConverterFactory(GsonConverterFactory.create())
.build();
return retrofit;
}
}
after that call the api into api interface..
public interface ApiInterface {
#GET("{affenpinscher}/images")
Call<Product> getProductData(#Path("affenpinscher") String breed);
#GET("getProductDetailByProductId?ProductId=3")
Call<JsonObject> ITEM_DESCRIPTION_RESPONSE_CALL();
#POST("linke")
Call<Response> passJsonData(#Body JsonData jsonData);
#GET("/users/waadalkatheri/repos")
Call<Response> getdata();
}
and when you call api in activity or fragment used below code..
ApiInterface apiInterface = ApiClient.getInstance().getClient().create(ApiInterface.class);
Call<ResponseData> responseCall = apiInterface.getdata();
responseCall.enqueue(new Callback<ResponseData>() {
#Override
public void onResponse(Call<ResponseData> call, retrofit2.Response<ResponseData> response) {
if (response.isSuccessful() && response.body() != null && response != null) {
Toast.makeText(getApplicationContext(), "GetData" + response.body().getLanguage(), Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<ResponseData> call, Throwable t) {
Log.d("Errror", t.getMessage());
}
});

How to POST with RxJava 2 + Retrofit 2?

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,
);

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.

Categories

Resources