Android项目中,主要用到Activity与layout布局,大体上即呈现MVC的结构,在Android开发中,常用到的开发模式有MVC、MVP、MVVM,在此作简要介绍。
Android项目入手,初学者都知道创建一个Activity,随后即产生一个界面,开启HelloWorld之旅。
由于此种模式的存在,项目自然而然呈现MVC模式,Model-View-Controller,layout作为布局文件,充当着视图View的角色,而Activity作为一个庞大的Controller,控制M和V,View接受交互请求,并把请求交给Controller,Controller操作Model进行数据更新,数据更新之后,Model通知View数据变化,从而使View显示更新之后的数据。
一个简单的例子:登录功能。
创建一个LoginActivity,界面中有两个输入框EditText与一个按钮Button,输入用户名密码来登录。登录功能代码如下:
public void login(View view){
String userName=et_username.getText().toString();
String passWord=et_password.getText().toString();
final User user=new User(userName,passWord);
doLogin(user);
}
private void doLogin(final User user){
new Thread(){
@Override
public void run() {
super.run();
//网络执行登录操作
booleanlogin=checkUserInfo(user);
if (login) {
runOnUiThread(newRunnable() {
@Override
public void run() {
Toast.makeText(LoginActivity.this,"登录成功",Toast.LENGTH_SHORT).show();
}
});
}else {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(LoginActivity.this,"登录失败",Toast.LENGTH_SHORT).show();
}
});
}
}
}.start();
}
除去User类封装了userName和passWord,其余所有代码都放在Activity中,这是一个简单的MVC模式,但是,显得很是臃肿,可以通过方法的抽取,把login()方法中的逻辑代码简化一下,但抽取出来的代码仍放在Activity中,如果一个界面中有很多逻辑功能,相对应的方法数就会有很多个,维护起来也略显繁杂。
Activity在上述功能中,由逻辑功能代码和界面显示代码组成,如果能将一部分抽取出去另外处理,可以对Activity进行瘦身。对C进行延伸,把业务逻辑抽取,产生了MVP(Model-View-Presenter)模式,对界面显示抽取,产生了MVVM(Model-View-ViewModel)模式。
View接受用户的交互请求,将请求转交给Presenter,Presenter操作Model进行数据更新,数据更新之后,Model通知Presenter数据发生变化,Presenter更新View的数据
首先写一个类LoginPresenter,把业务逻辑代码抽取到其中处理,并把与界面显示的代码还留在Activity中。那么,登录成功与否的逻辑需要在Activity中写一个方法来调用,那么,我们在LoginPresenter中需要调用LoginActivity中的代码,传入一个LoginActivity的对象可以解决这个问题,于是,创建一个构造函数LoginPresenter(LoginActivity activity)来传入LoginActivity对象,产生以下代码:
public classLoginPresenter {
private LoginActivity activity;
public LoginPresenter(LoginActivityactivity){
this.activity=activity;
}
private void doLogin(final User user){
new Thread(){
@Override
public void run() {
super.run();
//网络执行登录操作
booleanlogin=checkUserInfo(user);
if (login) {
activity.loginSuccess();
}else {
activity.loginFailure();
}
}
}.start();
}
private boolean checkUserInfo(User user){
//网络执行登录操作
return ...;
}
}
在LoginActivity中,写出登录成功与失败的界面处理代码如下:
public void loginSuccess() {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(LoginActivity.this,"登录成功",Toast.LENGTH_SHORT).show();
}
});
}
public void loginFailure() {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(LoginActivity.this,"登录失败",Toast.LENGTH_SHORT).show();
}
});
}
在LoginActivity中,只用创建一个LoginPresenter类的对象即可调用doLogin方法。
这时,思考一个问题,如果要使用的类的是Fragment呢?亦或者是其他任何类呢?显然,这种方式有局限性,好的做法是:不去传入LoginActivity的对象,而是定义一个接口对象传入,通过LoginActivity实现该接口,实现了两者的解耦合。而对于任何需要处理Presenter中功能的类,同样只要实现这个接口即可。定义接口类LoginInterface如下:
public interface LoginInterface {
void onLoginSuccess();
void onLoginFailure();
}
将上述LoginPresenter类代码中的LoginActivity改为LoginInterface,并将LoginActivity实现该接口,在两个实现方法中处理对应的结果界面显示。自此,MVP模式的登录功能就实现了。
而将Activity中与View有关的代码抽取出来,就是MVVM模式。
为了实现V与ViewModle之间的通信,在2015年Google的I/O大会上,推出DataBinding技术支持,目前支持API7及Gradle1.5.0以上。
在使用上很简单,只用在module的gradle文件的android{}中,配置:
dataBinding{
enabled true
}
代码实现具体以登录例子为参照,继续将项目改为MVVM。
首先将Activity中与View有关的代码删除,即setContentView()方法和findViewById()的代码。onCreat()方法中增加binding代码,如下:
@Override
protected void onCreate(@Nullable BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
ActivityLoginBinding binding=DataBindingUtil.setContentView(this,R.layout.activity_login);
}
在layout布局中,将原布局根节点外加一层
布局中的data即是对数据的绑定,将EditText中的数据显示与User中的数据绑定,而EditText数据变化时需要改变User中的值,因而添加TextWatcher。在此创建了一个UserEvent类,创建两个TextWatcher分别监听EditText变化,来改变User的值,实现ViewModle的功能。UserEvent代码如下:
public class UserEvent {
private User user;
public UserEvent(Useruser){
this.user=user;
}
public TextWatchernameWatcher=new TextWatcher() {
@Override
public voidbeforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public voidonTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public voidafterTextChanged(Editable s) {
user.setUserName(s.toString());
}
};
public TextWatcherpassWordWatcher=new TextWatcher() {
@Override
public voidbeforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public voidonTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public voidafterTextChanged(Editable s) {
user.setPassword(s.toString());
}
};
}
此时,在Activity的onCreate代码中增加数据绑定如下:
user=new User();
UserEvent event=newUserEvent(user);
binding.setEvent(event);
至此,把View部分的代码逻辑全部抽取出去,形成MVVM模式。
以上只是对MVC、MVP、MVVM在Android中应用的一个简单介绍,实际项目中,可以对项目结构进行更为简洁的拆分与解耦,具体功能见机行事即可。