I am working on (Login) screen using MVVM architecture pattern, faced an issue when call the API with wrong email or password and getting the response from API then write the correct email and password, the API didn't recall, the old response keep returns.
Also, am i using MVVM correct as it should be?
Here is my code
public interface LoginApi {
@POST("/api/Login")
Call<LoginResponse> login(@Body LoginParams loginParams);
}
public class RetrofitService {
private static Retrofit retrofit;
private static final Object LOCK = new Object();
private static final String BASE_URL = "https://base.url";
public static Retrofit getRetrofitInstance() {
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
@Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request original = chain.request();
Request.Builder requestBuilder = original.newBuilder()
.addHeader("Content-Type", "application/json");
Request request = requestBuilder.build();
return chain.proceed(request);
}
});
OkHttpClient client = httpClient.build();
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
httpClient.addInterceptor(logging);
httpClient.readTimeout(60, TimeUnit.SECONDS);
httpClient.connectTimeout(60, TimeUnit.SECONDS);
if (retrofit == null) {
synchronized (LOCK) {
retrofit = new retrofit2.Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build();
}
}
return retrofit;
}
public static <S> S createService(Class<S> serviceClass) {
return getRetrofitInstance().create(serviceClass);
}
}
public class LoginRepository {
private static LoginRepository loginRepository;
static LoginRepository getInstance() {
if (loginRepository == null) {
loginRepository = new LoginRepository();
}
return loginRepository;
}
private LoginApi loginApi;
private LoginRepository() {
loginApi = RetrofitService.createService(LoginApi.class);
}
public MutableLiveData<LoginResponse> login(LoginParams loginParams) {
MutableLiveData<LoginResponse> loginData = new MutableLiveData<>();
loginApi.login(loginParams).enqueue(new Callback<LoginResponse>() {
@Override
public void onResponse(Call<LoginResponse> call,
Response<LoginResponse> response) {
loginData.setValue(response.body());
}
@Override
public void onFailure(Call<LoginResponse> call, Throwable t) {
}
});
return loginData;
}
}
public class LoginViewModel extends ViewModel {
private MutableLiveData<LoginResponse> mutableLiveData;
private LoginRepository loginRepository;
private LoginParams loginParams = new LoginParams();
public void init(Map<String, String> loginMap) {
if (mutableLiveData != null) {
return;
}
loginRepository = LoginRepository.getInstance();
loginParams.setEmail(loginMap.get("loginEmail"));
loginParams.setPassword(loginMap.get("loginPassword"));
mutableLiveData = loginRepository.login(loginParams);
}
public LiveData<LoginResponse> getLoginRepository() {
return mutableLiveData;
}
}
public class LoginFragment extends BaseFragment {
@BindView(R.id.et_email_login)
AppCompatEditText etEmailLogin;
@BindView(R.id.et_password_login)
AppCompatEditText etPasswordLogin;
public static LoginFragment getInstance() {
return new LoginFragment();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View inflateFragmentView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_login, container, false);
ButterKnife.bind(this, view);
return view;
}
@OnClick(R.id.btn_enter_login)
public void onClickLogin() {
getMainActivity().showProgressBar();
LoginViewModel loginViewModel = ViewModelProviders.of(getActivity()).get(LoginViewModel.class);
loginViewModel.init(createLoginParam());
observeViewModel(loginViewModel);
loginViewModel.getLoginRepository();
}
private void observeViewModel(LoginViewModel loginViewModel) {
loginViewModel.getLoginRepository().observe(this, loginResponse -> {
getMainActivity().hideProgressBar();
if (loginResponse == null) {
// handle error here
return;
}
if (loginResponse.isSuccess()) {
getMainActivity().showResult(loginResponse.getUserId());
} else {
getMainActivity().showResult(loginResponse.getErrorMessage());
}
});
}
private Map<String, String> createLoginParam() {
Map<String, String> loginMap = new HashMap<>();
loginMap.put("loginEmail", etEmailLogin.getText().toString());
loginMap.put("loginPassword", etPasswordLogin.getText().toString());
return loginMap;
}
}
After a while i found my issue it was in LoginViewModel
as i didn't create new instance of mutableLiveData
i used the pre-created one which give same response each time. So my problem solved by removing this condition.
if (mutableLiveData != null) {
return;
}