【问题标题】:Unable to observe Livedata from ViewModel无法从 ViewModel 观察 Livedata
【发布时间】:2020-03-17 00:18:44
【问题描述】:

我在MVVM设计模式上实现了简单的手机号登录,但是服务器返回响应时没有调用Onchanged函数。

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();
}
}

登录库

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;
}

}

登录活动

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

}
}

我可以从日志中看到数据发布成功,响应也很完美。但是为livedata“loginresponse”赋值并不称为observable。

【问题讨论】:

    标签: android mvvm retrofit


    【解决方案1】:

    ViewModel 中删除loginResponse 并在Repository 中创建它,然后将存储库loginResponse 传递给您的活动。检查下面

    public class LoginRepository {
        public MutableLiveData<LoginResponse> loginResponse = new MutableLiveData<>();
        ...
    
        //getter
        public MutableLiveData<LoginResponse> getLoginResponse() {
            return loginResponse
        }
    }
    

    然后在 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);
            }
        }
    
        ...
    }
    

    在存储库中更改您的登录功能,如下所示:

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

    【讨论】:

    • 它有效,但是,这是设计 MVVM 模式的方式吗?
    • 为什么不呢。我只是更改了LiveData 传递方法而已。你必须 postValue 到那些 LiveData 你实际上是 observe
    • 在哪里验证视图模型或视图中的响应?
    【解决方案2】:

    来自文档

    您必须调用 setValue(T) 方法来更新 LiveData 对象 从主线程。如果代码在工作线程中执行,您 可以改用 postValue(T) 方法来更新 LiveData 对象。

    使用

     loginResponse.postValue(response.body());
    

    更多详情请参考LiveData Overview

    编辑:

    在 LoginRepository 中删除

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

    将值设置为 viewmodel LoginResponse 然后只有新值将 viemodel 传递给活动

    【讨论】:

      猜你喜欢
      • 2018-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多