当涉及到一般的设计模式时。您希望业务逻辑远离活动和片段。
如果您问我,MVVM 和 MVP 都是非常好的选择。但是既然你想实现 MVVM。然后我将尝试解释一下我是如何实现它的。
活动
public class LoginActivity extends BaseActivity {
private LoginActivityViewModel viewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityLoginBinding binding = DataBindingUtil.setContentView(this,R.layout.activity_login);
NavigationHelper navigationHelper = new NavigationHelper(this);
ToastHelper toastHelper = new ToastHelper(this);
ProgressDialogHelper progressDialogHelper = new ProgressDialogHelper(this);
viewModel = new LoginActivityViewModel(navigationHelper,toastHelper,progressDialogHelper);
binding.setViewModel(viewModel);
}
@Override
protected void onPause() {
if (viewModel != null) {
viewModel.onPause();
}
super.onPause();
}
@Override
protected void onDestroy() {
if (viewModel != null) {
viewModel.onDestroy();
}
super.onDestroy();
}
}
这是一个相当简单的活动。没什么特别的。我只是从实例化我的 viewModel 需要的东西开始。因为我试图让所有特定于 android 的东西远离它。一切都可以简化测试的编写
然后我只是将视图模型绑定到视图。
观点
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="viewModel"
type="com.community.toucan.authentication.login.LoginActivityViewModel" />
</data>
<RelativeLayout
android:id="@+id/activity_login_main_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/background"
tools:context="com.community.toucan.authentication.login.LoginActivity">
<ImageView
android:id="@+id/activity_login_logo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="40dp"
android:src="@drawable/logo_small" />
<android.support.v7.widget.AppCompatEditText
android:id="@+id/activity_login_email_input"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_below="@+id/activity_login_logo"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="60dp"
android:drawableLeft="@drawable/ic_email_white"
android:drawablePadding="10dp"
android:hint="@string/email_address"
android:inputType="textEmailAddress"
android:maxLines="1"
android:text="@={viewModel.username}" />
<android.support.v7.widget.AppCompatEditText
android:id="@+id/activity_login_password_input"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_below="@+id/activity_login_email_input"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:drawableLeft="@drawable/ic_lock_white"
android:drawablePadding="10dp"
android:hint="@string/password"
android:inputType="textPassword"
android:maxLines="1"
android:text="@={viewModel.password}" />
<Button
android:id="@+id/activity_login_main_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/activity_login_password_input"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:background="@drawable/rounded_button"
android:onClick="@{() -> viewModel.tryToLogin()}"
android:paddingBottom="10dp"
android:paddingLeft="60dp"
android:paddingRight="60dp"
android:paddingTop="10dp"
android:text="@string/login"
android:textColor="@color/color_white" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/activity_login_main_button"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"
android:onClick="@{() -> viewModel.navigateToRegister()}"
android:text="@string/signup_new_user"
android:textSize="16dp" />
<LinearLayout
android:id="@+id/activity_login_social_buttons"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerInParent="true"
android:layout_marginBottom="50dp"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/facebook" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/twitter" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/google" />
</LinearLayout>
<TextView
android:id="@+id/activity_login_social_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/activity_login_social_buttons"
android:layout_centerHorizontal="true"
android:layout_marginBottom="20dp"
android:text="@string/social_account"
android:textSize="16dp" />
</RelativeLayout>
</layout>
从视图一侧相当笔直。我绑定了 viewModel 需要对其具有的逻辑进行操作的所有特定值。
https://developer.android.com/topic/libraries/data-binding/index.html
检查以下链接以获取有关 android 数据绑定库如何工作的更多知识
视图模型
public class LoginActivityViewModel extends BaseViewModel implements FirebaseAuth.AuthStateListener {
private final NavigationHelper navigationHelper;
private final ProgressDialogHelper progressDialogHelper;
private final ToastHelper toastHelper;
private final FirebaseAuth firebaseAuth;
private String username;
private String password;
public LoginActivityViewModel(NavigationHelper navigationHelper,
ToastHelper toastHelper,
ProgressDialogHelper progressDialogHelper) {
this.navigationHelper = navigationHelper;
this.toastHelper = toastHelper;
this.progressDialogHelper = progressDialogHelper;
firebaseAuth = FirebaseAuth.getInstance();
firebaseAuth.addAuthStateListener(this);
}
@Override
public void onPause() {
super.onPause();
}
@Override
public void onResume() {
super.onResume();
}
@Override
public void onDestroy() {
firebaseAuth.removeAuthStateListener(this);
super.onDestroy();
}
@Override
public void onStop() {
progressDialogHelper.onStop();
super.onStop();
}
public void navigateToRegister() {
navigationHelper.goToRegisterPage();
}
public void tryToLogin() {
progressDialogHelper.show();
if (validInput()) {
firebaseAuth.signInWithEmailAndPassword(username, password)
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (!task.isSuccessful()) {
String message = task.getException().getMessage();
toastHelper.showLongToast(message);
}
progressDialogHelper.hide();
}
});
}
}
private boolean validInput() {
return true;
}
@Override
public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
if (firebaseAuth.getCurrentUser() != null) {
navigationHelper.goToMainPage();
}
}
@Bindable
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
notifyPropertyChanged(BR.username);
}
@Bindable
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
notifyPropertyChanged(BR.password);
}
}
所有的乐趣都在这里发生。我使用辅助类来展示和操作 android 系统。否则我尽量保持逻辑尽可能干净。一切都做好了,所以我更容易创建和测试逻辑。
记下
我将username 和password 与视图绑定。因此,对 EditText 所做的每一次更改都会自动添加到该字段中。以这种方式。我不需要添加任何特定的监听器
希望这个小展示可以帮助您了解如何将 MVVM 实施到您自己的项目中