Well, I will show you how I did, Handling API with retrofit & rxJava.
First create a ApiClient.class
public class ApiClient {
private static final String BASE_URL = "https://travellingbook.app/api/v2/";
public static final String IMAGE_BASE_URL = "";
private static File httpCacheDirectory = new File(UpasargaApplication.getAppContext().getCacheDir(), "new_responses");
private static int cacheSize = 10 * 1024 * 1024; // 10 MiB
private static Cache cache = new Cache(httpCacheDirectory, cacheSize);
private static Retrofit retrofit = null;
public static Retrofit getClient() {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
if (BuildConfig.DEBUG) {
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
} else {
interceptor.setLevel(HttpLoggingInterceptor.Level.NONE);
}
builder.interceptors().add(interceptor);
builder.authenticator(new ApiTokenAuthenticator());
OkHttpClient httpClient = builder
.readTimeout(15, TimeUnit.SECONDS)
.connectTimeout(15, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS)
.addInterceptor(new ApiInterceptor())
.build();
Gson gson = new GsonBuilder()
.setLenient()
.create();
RxJava2CallAdapterFactory rxJava2CallAdapterFactory = RxJava2CallAdapterFactory.createWithScheduler(Schedulers.computation());
if (retrofit == null) {
retrofit = new Retrofit.Builder().baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(rxJava2CallAdapterFactory)
.client(httpClient)
.build();
}
return retrofit;
}
Now, Add Interceptor.class and TokenAuthenticator.class (Based upon your rest API architecture. Here's a sample case.)
public class ApiInterceptor implements Interceptor {
@NonNull
@Override
public Response intercept(@NonNull Chain chain) throws IOException {
Request originalRequest = chain.request();
if (Utilities.getLoginResponse() == null || TextUtils.isEmpty(Utilities.getLoginUserToken())) {
return chain.proceed(originalRequest);
}
Request request = originalRequest.newBuilder()
.addHeader("Authorization", Utilities.getLoginUserToken())
.addHeader("Accept", "Accept: application/x.school.v1+json")
.header("Cache-Control", String.format("max-age=%d", 50000))
.build();
return chain.proceed(request);
}
}
Now Create a LoginApiService.java interface.
public interface LoginApiService {
@POST("login")
@FormUrlEncoded
Observable<Login> login(
@Field("email") String email,
@Field("password") String password
);
@POST("forgot_password")
@FormUrlEncoded
Observable<ServerResponse> forgotPassword(
@Field("email") String email
);
}
Now Implementing LoginPresenter.java Handles Logic.
public class LoginPresenter {
private static final String TAG = LoginPresenter.class.getSimpleName();
private WeakReference<View> view;
CompositeDisposable compositeDisposable;
public LoginPresenter(View view) {
this.view = new WeakReference<>(view);
this.compositeDisposable = new CompositeDisposable();
}
private View getView() throws NullPointerException {
if (view != null)
return view.get();
else
throw new NullPointerException("View is unavailable");
}
public void userLogin(String email, String password) {
Observable<Login> loginObservable = ApiClient.getClient().create(LoginApiService.class)
.login(email, password)
.subscribeOn(Schedulers.io())
.retry(AppConstants.API_RETRY_COUNT)
.observeOn(AndroidSchedulers.mainThread());
DisposableObserver<Login> loginDisposableObserver = new DisposableObserver<Login>() {
@Override
public void onNext(Login login) {
if (getView() != null && login != null) {
getView().onUserLoginSuccess(login);
}
}
@Override
public void onError(Throwable e) {
try {
getView().onFailure(UtilitiesFunctions.handleApiError(e));
} catch (Exception ignored) {
}
}
@Override
public void onComplete() {
}
};
compositeDisposable.add(loginObservable.subscribeWith(loginDisposableObserver));
}
public void forgotPassword(String email) {
Observable<ServerResponse> loginObservable = ApiClient.getClient().create(LoginApiService.class)
.forgotPassword(email)
.subscribeOn(Schedulers.io())
.retry(AppConstants.API_RETRY_COUNT)
.observeOn(AndroidSchedulers.mainThread());
DisposableObserver<ServerResponse> loginDisposableObserver = new DisposableObserver<ServerResponse>() {
@Override
public void onNext(ServerResponse serverResponse) {
Log.e("onNext: ", new GsonBuilder().create().toJson(serverResponse));
if (getView() != null && serverResponse != null) {
getView().onForgotPasswordSuccess(serverResponse);
}
}
@Override
public void onError(Throwable e) {
ServerResponse serverResponse = new GsonBuilder().create().fromJson(e.getMessage(), ServerResponse.class);
if (serverResponse != null) {
getView().onFailure(serverResponse.getMessage());
} else {
try {
getView().onFailure(UtilitiesFunctions.handleApiError(e));
} catch (Exception ignored) {
}
}
}
@Override
public void onComplete() {
}
};
compositeDisposable.add(loginObservable.subscribeWith(loginDisposableObserver));
}
public void onActivityStop() {
if (getView() != null) {
compositeDisposable.clear();
}
}
public interface View {
void onUserLoginSuccess(Login login);
void onForgotPasswordSuccess(ServerResponse serverResponse);
void onFailure(String message);
}
Finally, we can access LoginPresenter.class from Activity/Fragment
public class LoginActivity extends AppActivity implements LoginPresenter.View {
private Button btnLogin;
private LoginPresenter loginPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
enter code here
loginPresenter = new LoginPresenter(this);
}
@Override
public void onUserLoginSuccess(Login login) {
if (login != null) {
Utilities.saveLoginResponse(login);
Utilities.saveLoginResponse(login);
hideProgressBarWork();
if (login.getStatus()) {
Utilities.setUserLoginCompleted();
} else {
ShowToastWithMessage("Your account has been disabled.");
}
}
}
@Override
public void onForgotPasswordSuccess(ServerResponse serverResponse) {
}
@Override
public void onFailure(String message) {
hideProgressBarWork();
ShowToastWithMessage(message);
}
}
Queries & Suggestions are welcome.