英文:
Android MVVM Repository and ViewModel Question
问题
我刚刚开始使用MVVM模式。当我尝试进行登录时遇到了一些问题。以下是我的代码。
**1. 登录服务**
```java
public interface LoginService {
@FormUrlEncoded
@POST("user/login")
Call<JsonObject> validateLogin(@Field("phoneNum") String phoneNum, @Field("password") String password);
}
2. 仓库(Repository)
public class LoginRepository {
private static final String TAG = "LoginRepository";
private static LoginRepository instance;
public static LoginRepository getInstance() {
if (instance == null) {
instance = new LoginRepository();
}
return instance;
}
public MutableLiveData<JsonObject> getLoginMessage(String phoneNum, String password) {
final MutableLiveData<JsonObject> message = new MutableLiveData<>();
LoginService service = RetrofitClass.getLoginService();
Call<JsonObject> call = service.validateLogin(phoneNum, password);
call.enqueue(new Callback<JsonObject>() {
@Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
if (response.isSuccessful()) {
JsonObject info = response.body();
message.setValue(info);
}
}
@Override
public void onFailure(Call<JsonObject> call, Throwable t) {
Log.d(TAG, "fail!");
message.setValue(null);
}
});
return message;
}
}
3. 视图模型(ViewModel)
方法 queryRepo
用于使用手机号和密码请求登录服务。当用户点击登录按钮时会使用该方法。
public class LoginViewModel extends ViewModel {
private static final String TAG = "UserProfileViewModel";
private LoginRepository mLoginRepository;
private MutableLiveData<JsonObject> message = new MutableLiveData<>();
public void queryRepo(String phoneNum, String password) {
this.message = mLoginRepository.getLoginMessage(phoneNum, password);
}
public LiveData<JsonObject> getMessage() {
return message;
}
}
4. 活动(Activity)
登录
public class LoginActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "LoginActivity";
private TextView mForgetPswTv, mRegisterTv;
private EditText mPhoneEdt, mPasswordEdt;
private QMUIRoundButton mLoginBtn;
private ProgressBar mProgressBar;
private LoginViewModel mLoginViewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().hide();
setContentView(R.layout.activity_login);
initView();
bindOperation();
mLoginViewModel = new ViewModelProvider(this).get(LoginViewModel.class);
mLoginViewModel.getMessage().observe(this, new Observer<JsonObject>() {
@Override
public void onChanged(JsonObject jsonObject) {
if (jsonObject != null) {
mProgressBar.setVisibility(View.GONE);
mPasswordEdt.setText(jsonObject.toString());
} else Log.d(TAG, "null");
}
});
}
private void initView() {
mProgressBar = (ProgressBar) findViewById(R.id.progress_circular_movie_article);
mForgetPswTv = findViewById(R.id.forget_psw_tv);
mRegisterTv = findViewById(R.id.register_tv);
mLoginBtn = findViewById(R.id.login_btn);
mPhoneEdt = findViewById(R.id.phone_edt);
mPasswordEdt = findViewById(R.id.password_edt);
}
private void bindOperation() {
mForgetPswTv.setOnClickListener(LoginActivity.this);
mRegisterTv.setOnClickListener(LoginActivity.this);
mLoginBtn.setOnClickListener(v -> {
mLoginViewModel.queryRepo(mPhoneEdt.getText().toString(), mPasswordEdt.getText().toString());
});
}
}
我认为代码写得很清楚,但我真的不知道为什么它不起作用。当我点击登录按钮时,this.message.getValue()
会变成 null。我是否遗漏了重要的内容?实际上,如果我不初始化 message,第一次调用 queryRepo
是有效的,但一旦 message 被赋值,如果我再次调用 queryRepo
,message.getValue()
就会变成 null。
<details>
<summary>英文:</summary>
I have just start my MVVM pattern. And when I do the login, I have some problems. Here is my code.
**1. login service**
```java
public interface LoginService {
@FormUrlEncoded
@POST("user/login")
Call<JsonObject> validateLogin(@Field("phoneNum") String phoneNum, @Field("password") String password);
}
2. Repository
public class LoginRepository {
private static final String TAG = "LoginRepository";
private static LoginRepository instance;
public static LoginRepository getInstance() {
if (instance == null) {
instance = new LoginRepository();
}
return instance;
}
public MutableLiveData<JsonObject> getLoginMessage(String phoneNum, String password) {
final MutableLiveData<JsonObject> message = new MutableLiveData<>();
LoginService service = RetrofitClass.getLoginService();
Call<JsonObject> call = service.validateLogin(phoneNum, password);
call.enqueue(new Callback<JsonObject>() {
@Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
if (response.isSuccessful()) {
JsonObject info = response.body();
message.setValue(info);
}
}
@Override
public void onFailure(Call<JsonObject> call, Throwable t) {
Log.d(TAG, "fail!");
message.setValue(null);
}
});
return message;
}
}
3. viewmodel
the method queryRepo
is to request login service using phoneNum and password. And it will be used when user click the login button.
public class LoginViewModel extends ViewModel {
private static final String TAG = "UserProfileViewModel";
private LoginRepository mLoginRepository;
private MutableLiveData<JsonObject> message = new MutableLiveData<>();
public void queryRepo(String phoneNum, String password) {
this.message = mLoginRepository.getLoginMessage(phoneNum, password);
}
public LiveData<JsonObject> getMessage() {
return message;
}
}
4. Activity
login
public class LoginActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "LoginActivity";
private TextView mForgetPswTv, mRegisterTv;
private EditText mPhoneEdt, mPasswordEdt;
private QMUIRoundButton mLoginBtn;
private ProgressBar mProgressBar;
private LoginViewModel mLoginViewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().hide();
setContentView(R.layout.activity_login);
initView();
bindOperation();
mLoginViewModel = new ViewModelProvider(this).get(LoginViewModel.class);
mLoginViewModel.getMessage().observe(this, new Observer<JsonObject>() {
@Override
public void onChanged(JsonObject jsonObject) {
if (jsonObject != null) {
mProgressBar.setVisibility(View.GONE);
mPasswordEdt.setText(jsonObject.toString());
} else Log.d(TAG, "null");
}
});
}
private void initView() {
mProgressBar = (ProgressBar) findViewById(R.id.progress_circular_movie_article);
mForgetPswTv = findViewById(R.id.forget_psw_tv);//忘记密码
mRegisterTv = findViewById(R.id.register_tv);//立即注册
mLoginBtn = findViewById(R.id.login_btn);
mPhoneEdt = findViewById(R.id.phone_edt);
mPasswordEdt = findViewById(R.id.password_edt);
}
private void bindOperation() {
mForgetPswTv.setOnClickListener(LoginActivity.this);
mRegisterTv.setOnClickListener(LoginActivity.this);
mLoginBtn.setOnClickListener(v -> {
mLoginViewModel.queryRepo(mPhoneEdt.getText().toString(), mPasswordEdt.getText().toString());
});
}
}
I think it's clear, but I really don't know why it doesn't work, When I touch the login button, this.message.getValue()
will change to null. is there something important that I missed?
actually, if I don't initialize the message, the first time I call queryRepo is fine, but once the message is assigned a value, if I call queryRepo again, message.getValue() will be null.
答案1
得分: 1
我终于成功了,就像下面这样。
mLoginBtn.setOnClickListener(v -> {
mLoginViewModel.queryRepo(mPhoneEdt.getText().toString(), mPasswordEdt.getText().toString());
mLoginViewModel.getMessage().observe(this, new Observer<JsonObject>() {
@Override
public void onChanged(JsonObject jsonObject) {
if (jsonObject != null) {
mProgressBar.setVisibility(View.GONE);
mPasswordEdt.setText(jsonObject.toString());
} else Log.d(TAG, "null");
}
});
});
再次感谢大家!
英文:
I finally made it, just as below.
mLoginBtn.setOnClickListener(v -> {
mLoginViewModel.queryRepo(mPhoneEdt.getText().toString(), mPasswordEdt.getText().toString());
mLoginViewModel.getMessage().observe(this, new Observer<JsonObject>() {
@Override
public void onChanged(JsonObject jsonObject) {
if (jsonObject != null) {
mProgressBar.setVisibility(View.GONE);
mPasswordEdt.setText(jsonObject.toString());
} else Log.d(TAG, "null");
}
});
});
Thanks for everybody again!
答案2
得分: 0
尝试在按钮的点击监听器中观察实时数据,就像这样,并进行检查:
mLoginBtn.setOnClickListener(v -> {
mLoginViewModel.queryRepo(mPhoneEdt.getText().toString(), mPasswordEdt.getText().toString());
mLoginViewModel.getMessage().observe(this, new Observer<JsonObject>() {
@Override
public void onChanged(JsonObject jsonObject) {
if (jsonObject != null) {
mProgressBar.setVisibility(View.GONE);
mPasswordEdt.setText(jsonObject.toString());
} else Log.d(TAG, "null");
}
});
});
英文:
Try to Observe live data into Button OnClickListener, Like this, and check
mLoginBtn.setOnClickListener(v -> {
mLoginViewModel.queryRepo(mPhoneEdt.getText().toString(), mPasswordEdt.getText().toString());
mLoginViewModel.getMessage().observe(this, new Observer<JsonObject>() {
@Override
public void onChanged(JsonObject jsonObject) {
if (jsonObject != null) {
mProgressBar.setVisibility(View.GONE);
mPasswordEdt.setText(jsonObject.toString());
} else Log.d(TAG, "null");
}
});
});
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论