简体   繁体   中英

Unable to observe Livedata from ViewModel

I have implemented simple a mobile number login on MVVM design pattern.But the Onchanged function is not called when the response is returned from the server.

LoginViewModel

public class LoginViewModel extends ViewModel {

private LoginModel login;
private MutableLiveData<LoginResponse> loginresponse = new MutableLiveData<>();
private LoginRepository loginrepository;


public void init() {
    login = new LoginModel();
}


public LoginModel getLogin() {
    return login;
}


public void onLoginClick() {
   if(login.isPhonevalid()){
       HashMap<String,Object> loginObject = new HashMap<>();
       loginObject.put("phonenumber",login.getMobileNumber());
       loginObject.put("apimethod","beatme");
       loginresponse = LoginRepository.getInstance().login(loginObject);
      // loginClick.setValue(login);
      }
}


@BindingAdapter("error")
public static void setError(EditText editText, String errormessage) {
    editText.setError(errormessage);

}


public MutableLiveData<LoginResponse> getLoginresponse() {
    return loginresponse;
}


public String getMobileNo(){
    return login.getMobileNumber();
}
}

LoginRepository

public class LoginRepository {


private static LoginRepository loginRepository;
private Api api;

public static LoginRepository getInstance() {
    if (loginRepository == null) {
        loginRepository = new LoginRepository();
    }
    return loginRepository;
}


public LoginRepository() {
    api = RetrofitService.createService(Api.class);
}


public MutableLiveData<LoginResponse> login(HashMap<String, Object> body) {

    final MutableLiveData<LoginResponse> loginResponse = new MutableLiveData<>();
    api.login(body).enqueue(new Callback<LoginResponse>() {
        @Override
        public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) {
            if (response.isSuccessful()) {
                loginResponse.setValue(response.body());
            }
        }

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

    return loginResponse;
}

}

LoginActivity

public class LoginActivity extends AppCompatActivity {

private LoginViewModel viewModel;
ActivityLoginBinding activityLoginBinding;




boolean doubleBackToExitPressedOnce = false;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_login);
    getSupportActionBar().hide();
    activityLoginBinding  = DataBindingUtil.setContentView(LoginActivity.this, R.layout.activity_login);

    viewModel = ViewModelProviders.of(this).get(LoginViewModel.class);
    if (savedInstanceState == null) {
        viewModel.init();
    }
    activityLoginBinding.setLoginViewModel(viewModel);
    setuploginclick();

}

public void setuploginclick() {
    viewModel.getLoginresponse().observe(this, new Observer<LoginResponse>() {
        @Override
        public void onChanged(LoginResponse loginResponse) {

            Toast.makeText(LoginActivity.this,viewModel.getMobileNo(),Toast.LENGTH_SHORT).show();
            Intent i = new Intent(LoginActivity.this, OTPVerify.class);
            i.putExtra("mobileno",viewModel.getMobileNo());
            startActivity(i);
        }
    });

}
}

I can see from the log that the data is posted success and the response too is perfect. But assigning value to the livedata "loginresponse" doesn't call observable.

From the documents

You must call the setValue(T) method to update the LiveData object from the main thread. If the code is executed in a worker thread, you can use the postValue(T) method instead to update the LiveData object.

use

 loginResponse.postValue(response.body());

more detail refer LiveData Overview

Edit:

In LoginRepository remove

 final MutableLiveData<LoginResponse> loginResponse = new MutableLiveData<>();

set value to viewmodel LoginResponse then only new value pass viemodel to activity

Remove loginResponse from ViewModel and create it in Repository then pass repository loginResponse to your activity. Check below

public class LoginRepository {
    public MutableLiveData<LoginResponse> loginResponse = new MutableLiveData<>();
    ...

    //getter
    public MutableLiveData<LoginResponse> getLoginResponse() {
        return loginResponse
    }
}

then in ViewModel:

public class LoginViewModel extends ViewModel {
    ...

    public MutableLiveData<LoginResponse> getLoginResponse() {
        return LoginRepository.getInstance().getLoginResponse()
    }

    ...

    public void onLoginClick() {
        if(login.isPhonevalid()){
            HashMap<String,Object> loginObject = new HashMap<>();
            loginObject.put("phonenumber",login.getMobileNumber());
            loginObject.put("apimethod","beatme");
            LoginRepository.getInstance().login(loginObject);
            // loginClick.setValue(login);
        }
    }

    ...
}

Change your login function in Repository like below:

public void login(HashMap<String, Object> body) {

    api.login(body).enqueue(new Callback<LoginResponse>() {
        @Override
        public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) {
            if (response.isSuccessful()) {
                loginResponse.postValue(response.body());
            }
        }

        @Override
        public void onFailure(Call<LoginResponse> call, Throwable t) {
            loginResponse.postValue(null);
        }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM