I checked this article but observe the response changes in MainActivity.

Here is my code for LoginRepo

public MutableLiveData<LoginResponseModel> checkLogin(LoginRequestModel loginRequestModel) {
    final MutableLiveData<LoginResponseModel> data = new MutableLiveData<>();
    Map<String, String> params = new HashMap<>();
    params.put("email", loginRequestModel.getEmail());
    params.put("password", loginRequestModel.getPassword());
    apiService.checkLogin(params)
            .enqueue(new Callback<LoginResponseModel>() {
                @Override
                public void onResponse(Call<LoginResponseModel> call, Response<LoginResponseModel> response) {
                    if (response.isSuccessful()) {
                        data.setValue(response.body());
                        Log.i("Response ", response.body().getMessage());
                    }
                }

                @Override
                public void onFailure(Call<LoginResponseModel> call, Throwable t) {
                    data.setValue(null);
                }
            });
    return data;
}

Here is my Code LoginViewModel

public class LoginViewModel extends ViewModel {


public MutableLiveData<String> emailAddress = new MutableLiveData<>();
public MutableLiveData<String> password = new MutableLiveData<>();
Map<String, String> params = new HashMap<>();
LoginRepo loginRepo;

private MutableLiveData<LoginResponseModel> loginResponseModelMutableLiveData;


public LiveData<LoginResponseModel> getUser() {
    if (loginResponseModelMutableLiveData == null) {
        loginResponseModelMutableLiveData = new MutableLiveData<>();
        loginRepo = LoginRepo.getInstance();
    }

    return loginResponseModelMutableLiveData;
}


//This method is using Retrofit to get the JSON data from URL
private void checkLogin(LoginRequestModel loginRequestModel) {
    loginResponseModelMutableLiveData = loginRepo.checkLogin(loginRequestModel);
}

public void onLoginClick(View view) {
    LoginRequestModel loginRequestModel = new LoginRequestModel();
    loginRequestModel.setEmail(emailAddress.getValue());
    loginRequestModel.setPassword(password.getValue());
    params.put("email", loginRequestModel.getEmail());
    params.put("password", loginRequestModel.getPassword());
    checkLogin(loginRequestModel);
}

}

Here is my code for LoginActivity

 private LoginViewModel loginViewModel;
private ActivityMainBinding binding;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    loginViewModel = ViewModelProviders.of(this).get(LoginViewModel.class);
    binding = DataBindingUtil.setContentView(LoginActivity.this, R.layout.activity_main);
    binding.setLifecycleOwner(this);
    binding.setLoginViewModel(loginViewModel);
    loginViewModel.getUser().observe(this, new Observer<LoginResponseModel>() {
        @Override
        public void onChanged(@Nullable LoginResponseModel loginUser) {
            if (loginUser != null) {
                binding.lblEmailAnswer.setText(loginUser.getUser().getId());
                Toast.makeText(getApplicationContext(), loginUser.getUser().getId(), Toast.LENGTH_SHORT).show();
            }

        }
    });

}

onLoginClick method used in LoginViewModel is using LiveData.

The Response coming from api is okay. But onchange() it is not shown, how to use LiveData using MVVM pattern in simple Login Example. Please help!

1 Answers

0
Hossam Eldeen Onsy On

Here is what i have tried using your classes just altering retrofit to background thread to wait 5 seconds and then setting the data (you need to confirm the response being successful as you don't change the data if it's failing and hence if the loginResponseModel is null then it will enter the onChanged Method but it won't do anything as you don't have a condition if it is equals to null) here is what i did

in Main Activity -> onCreate() i just created the viewmodel and observed on the mutableLiveData

myViewModel.onLoginClick(null);
        myViewModel.simpleModelMutableLiveData.observe(this, new Observer<String>() {
            @Override
            public void onChanged(@Nullable String s) {
                if(s==null)
                  Log.v("testinggg","test - onChanged --- Null " );
                else
                    Log.v("testinggg","test - onChanged --- s -> "+s );
            }
        });

Then here is the ViewModel -> in which you will have the MutableLiveData itself named simpleModelMutableLiveData

     MutableLiveData<String> simpleModelMutableLiveData;


    public LiveData<String> getUser() {
        if (simpleModelMutableLiveData == null) {
            simpleModelMutableLiveData = new MutableLiveData<>();

        }

        return simpleModelMutableLiveData;
    }

  // this method will return Object of MutableLiveData<String> and let the simpleModelMutableLiveData be the returned object
    private void checkLogin(String placeholder) {
        simpleModelMutableLiveData = MyRepo.checkLogin(placeholder);
    }

    public void onLoginClick(View view) {

        checkLogin("test");
    }

and at last the Repo method in which i will return the MutableLiveData and let the simpleModelMutableLiveData to be the return and initiate a background thread using runnable that will wait 5 seconds before it sets the value using a handler (in your case you will need to set the value of the data after enqueue inside the Overridden Methods onResponse and onFailure)

as follows

public static MutableLiveData<String> checkLogin(String test) {
        final MutableLiveData<String> data = new MutableLiveData<>();


        Runnable r = new Runnable() {
            public void run() {
                runYourBackgroundTaskHere(data);
            }
        };

        new Thread(r).start();



        return data;
    }

     private static void runYourBackgroundTaskHere(final MutableLiveData<String> data) {

        try {
            Thread.sleep(5000);
//            Handler handler  = new Handler();
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    // things to do on the main thread

                /* Here i set the data to sss and then null and when 
                   you check the logcat and type the keyword used for 
                   logging which is "testinggg" 
                   you will find it show sss and then null which means 
                   it has entered the onChanged and showed you the log */

                    data.setValue("sss"); 
                    data.setValue(null);
                }
            });

        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }