我正在尝试研究MVVM模式,不知道在哪里放置改造电话 在MVVM模式中以及如何处理其响应
这是我的loginviewmodel类
public class LoginViewModel extends ViewModel {
public MutableLiveData<String> email = new MutableLiveData<>();
public MutableLiveData<String> password = new MutableLiveData<>();
public MutableLiveData<String> token = new MutableLiveData<>();
private MutableLiveData<Login> userMutableLiveData;
public MutableLiveData<Login> getUser() {
if (userMutableLiveData == null) {
userMutableLiveData = new MutableLiveData<>();
}
return userMutableLiveData;
}
public void onClick(View view) {
Login loginUser = new Login(email.getValue(), password.getValue());
userMutableLiveData.setValue(loginUser);
loginAccount(loginUser);
}
private void loginAccount(final Login login) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Api.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
Api api = retrofit.create(Api.class);
Call<Token> call = api.login(new Login(login.getEmail(), login.getPassword()));
call.enqueue(new Callback<Token>() {
@Override
public void onResponse(Call<Token> call, Response<Token> response) {
//finally we are setting the list to our MutableLiveData
userMutableLiveData.setValue(new Login(login.getEmail(), login.getPassword(),"Login Successful"));
}
@Override
public void onFailure(Call<Token> call, Throwable t) {
}
});
}
}
这是我在mainactivity中的oncreate
loginViewModel = ViewModelProviders.of(this).get(LoginViewModel.class);
binding = DataBindingUtil.setContentView(MainActivity.this, R.layout.activity_main);
binding.setLifecycleOwner(this);
binding.setLoginViewModel(loginViewModel);
loginViewModel.getUser().observe(this, new Observer<Login>() {
@Override
public void onChanged(@Nullable Login loginUser) {
if (TextUtils.isEmpty(Objects.requireNonNull(loginUser).getEmail())) {
binding.txtEmailAddress.setError("Enter an E-Mail Address");
binding.txtEmailAddress.requestFocus();
} else if (!loginUser.isEmailValid()) {
binding.txtEmailAddress.setError("Enter a Valid E-mail Address");
binding.txtEmailAddress.requestFocus();
} else if (TextUtils.isEmpty(Objects.requireNonNull(loginUser).getPassword())) {
binding.txtPassword.setError("Enter a Password");
binding.txtPassword.requestFocus();
} else if (!loginUser.isPasswordLengthGreaterThan5()) {
binding.txtPassword.setError("Enter at least 6 Digit password");
binding.txtPassword.requestFocus();
} else if (loginUser.getToken().equals("")) {
Toast.makeText(getApplicationContext(), "Login Failed", Toast.LENGTH_SHORT).show();
} else {
binding.tvToken.setText(loginUser.getToken());
}
}
});
我的activity_main.xml中也有一个textview,我希望在收到对API调用的响应(无论成功还是失败)之后,将响应发布到textview中。
我想知道这是正确的还是更好的方法?
谢谢!
答案 0 :(得分:1)
应该为您的应用程序处理业务逻辑的视图模型。最好将您的API调用放在Repository类中,请参见下面的示例:
首先,为整个应用程序创建一个API层
object RestApiHelper {
private lateinit var retrofit: Retrofit
private const val CONNECTION_TIME_OUT: Long = 60
fun getService(): NetworkService {
retrofit = Retrofit.Builder()
.baseUrl(BuildConfig.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(getClient())
.build()
return retrofit.create(NetworkService::class.java)
}
}
然后是用于调用API的存储库类
object LoginRepo {
//Create Retrofit service to hit apis
private val webService = RestApiHelper.getService()
// Create function here to login
fun login(
successHandler: (Token) -> Unit,
errorHandler: (ApiError) -> Unit,
connectionError: (Throwable?) -> Unit,
request: Login
) {
webService.login(request).enqueue(object : Callback< Token > {
override fun onResponse(call: Call< Token >?, response: Response< Token >?) {
response?.body()?.let {
// success response
}
}
override fun onFailure(call: Call< Token >?, t: Throwable?) {
}
})
}
}
从ViewModel类中,只需调用此仓库
class LoginViewModel : BaseViewModel() {
var mApiSuccess = MutableLiveData<Token>()
fun serverLogin(request: Login) {
LoginRepo.login({
mApiSuccess.value = it // Lambda function
}, {
mApiError.value = it // Lambda function
}, {
mConnectionFailure.value = it // Lambda function
}, request)
}
}
和BaseViewModel
open class BaseViewModel : ViewModel() {
var mApiError = MutableLiveData<ApiError>()
var mConnectionFailure = MutableLiveData<Throwable>()
}
通过这种方式,您只需将关注点分开,ViewModel就会从存储库中查询数据,现在您的存储库将提供您喜欢的源(网络/缓存/文件系统/数据库)中的数据,而您的模型永远都不知道数据源。 现在:
视图:负责UI
模型:业务逻辑
回购:数据提供者