小试Android中使用MVC框架模式

千磨万击还坚劲,任尔东西南北风。这篇文章主要讲述小试Android中使用MVC框架模式相关的知识,希望能为你提供帮助。
MVC简介      关于MVC网上的说法成千上万,每个人都有自己的理解,下面只是我个人现阶段学习的理解,欢迎指出不足之处~    MVC(Model View Controller 模型-视图-控制器)

  • Model(模型)直接操作数据层(如数据库记录的读写等),通常有最重的处理任务
  • View(视图) 直接面向用户数据展示界面,接受用户的数据输入并传递给控制层
  • Controller(控制器)业务逻辑处理层,本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后再确定用哪个视图来显示返回的数据
那么,MVC各层与android又有什么对应关系呢?
  • Model:负责数据处理相关的逻辑,通知View改变,会常涉及到网络请求及Android中的datebase、SharePreference等。
  • View:自定义View或ViewGroup,负责将用户的请求通知Controller,并根据model更新界面;
  • Controller:接收用户请求并更新model;
下面以一个简单的登录demo示例。
    使用安卓自带的SQLite建立一个用户,在登录时输入用户名和密码后匹配数据库记录,并显示登录成功或者失败的原因等。
小试Android中使用MVC框架模式

文章图片

其中,bean中User为实体类,包括用户名和密码;callback作为回调接口在控制层和模型层传递数据处理结果;db为帮助我们在数据库建立一个用户,并提供查询;
小试Android中使用MVC框架模式

文章图片
小试Android中使用MVC框架模式

文章图片
public class User {private String name; private String pwd; public String getPwd() { return pwd; }public void setPwd(String pwd) { this.pwd = pwd; }public String getName() {return name; }public void setName(String name) { this.name = name; }

User
小试Android中使用MVC框架模式

文章图片
小试Android中使用MVC框架模式

文章图片
public interface LoginCallBack { void success(User user); void fail(int status); }

View Code
小试Android中使用MVC框架模式

文章图片
小试Android中使用MVC框架模式

文章图片
1 public class MyDataBaseHelper extends SQLiteOpenHelper { 2 3 4private static final String CREATE_LOGIN = "create table LoginInfo(" + 5"id integer primary key autoincrement," + 6"name text," + 7"password text)"; 8 9 10public MyDataBaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) { 11super(context, name, factory, version); 12} 13 14@Override 15public void onCreate(SQLiteDatabase db) { 16db.execSQL(CREATE_LOGIN); 17} 18 19@Override 20public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 21 22} 23 24public void initData(SQLiteDatabase db) { 25 26String sql = "insert into LoginInfo(name,password) values(‘test‘,‘test‘)"; 27db.execSQL(sql); 28 //ContentValues values= new ContentValues(); 29 //values.put("name","test"); 30 //values.put("password","test"); 31 //db.insert("LoginInfo",null,values); 32 33} 34 35public int queryData( User user) { 36 37String sql = "select * from LoginInfo where name=?"; 38Cursor cursor = this.getReadableDatabase().rawQuery(sql, new String[]{user.getName()}); 39 40try{ 41if (cursor.moveToFirst()) { 42if (cursor.getString(cursor.getColumnIndex("password")).equals(user.getPwd())) { 43 44return 1; //正确 45} else { 46return 0; //密码错误 47} 48} 49return -1; //用户名错误(没有当前用户) 50}catch (Exception e){ 51e.printStackTrace(); 52}finally { 53cursor.close(); 54} 55return -2; //发生错误 56 57}

View Code 
先从View层讲起:自定义一个LoginView继承自LinearLayout
小试Android中使用MVC框架模式

文章图片
小试Android中使用MVC框架模式

文章图片
< ?xml version="1.0" encoding="utf-8"?> < prodigalwang.androidframe.mvc.view.LoginView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/activity_login_mvc" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> < EditText android:id="@+id/et_name_mvc" android:layout_width="200dp" android:layout_height="40dp" android:layout_gravity="center_horizontal" android:hint="请输入用户名" /> < EditText android:id="@+id/et_pwd_mvc" android:layout_width="200dp" android:layout_height="40dp" android:layout_gravity="center_horizontal" android:hint="请输入密码" android:inputType="textPassword" /> < Button android:id="@+id/bt_login_mvc" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginTop="20dp" android:text="登录" /> < /prodigalwang.androidframe.mvc.view.LoginView>

View Code通常我们直接在activity中直接初始化各种控件,而我们这样做之后只不过是将布局的初始化化代码移入到自定义的view中。
1 /** 2* Author:ProdigalWang 3* Time: 2016/9/26 4* 视图层,直接展示给用户。通过视图层将数据请求传送到控制层(Controller) 5* 作为视图层来说,它只是作为接受用户数据和展示数据的方式 6*/ 7 public class LoginView extends LinearLayout { 8 9private Context mContext; 10private EditText mUsername; 11private EditText mPassword; 12private Button mLoginBtn; 13 14public LoginView(Context context, AttributeSet attrs) { 15super(context, attrs); 16mContext = context; 17} 18 19public void initView() { 20mUsername = (EditText) findViewById(R.id.et_name_mvc); 21mPassword = (EditText) findViewById(R.id.et_pwd_mvc); 22mLoginBtn = (Button) findViewById(R.id.bt_login_mvc); 23} 24 25public String getName() { 26return mUsername.getText().toString(); 27} 28 29public String getPwd() { 30return mPassword.getText().toString(); 31} 32 33public void setOnclikLister(OnClickListener onclikLister) { 34mLoginBtn.setOnClickListener(onclikLister); 35} 36 37public void userNameEpty() { 38Toast.makeText(mContext, "用户名不能为空", Toast.LENGTH_SHORT).show(); 39} 40 41public void passWordEpty() { 42Toast.makeText(mContext, "密码不能为空", Toast.LENGTH_SHORT).show(); 43} 44 45public void userNameError() { 46Toast.makeText(mContext, "用户名错误", Toast.LENGTH_SHORT).show(); 47} 48 49public void passWordError() { 50Toast.makeText(mContext, "密码错误", Toast.LENGTH_SHORT).show(); 51} 52 53public void loginSuccess() { 54Toast.makeText(mContext, "登录成功", Toast.LENGTH_SHORT).show(); 55} 56 57public void loginFailure() { 58Toast.makeText(mContext, "登录失败", Toast.LENGTH_SHORT).show(); 59} 60 }

这样我们就完成了View层的抽取。
下面实现Model层:首先我们需要先抽取出一个接口,由于我们的需求很简单,只是一个登陆操作,只需要验证用户输入的用户名和密码是否正确,所以我们的抽取的接口中也只有一个login()方法。
/** * 模型层— — — 登录接口 */public interface ILoginModel {void login(String name, String pwd, LoginCallBack loginCallBack); }

/** * Author:ProdigalWang * Time: 2016/9/26 * 模型层实现,完成具体的数据操作。 */public class LoginModelImpl implements ILoginModel {private MyDataBaseHelper myDataBaseHelper; @Override public void login(String name, String pwd, LoginCallBack loginCallBack) {User user=new User(); user.setName(name); user.setPwd(pwd); myDataBaseHelper = new MyDataBaseHelper(MyAppliction.getContext(), "Login.db", null, 1); int result = myDataBaseHelper.queryData(user); //发出处理结果,用户得到反馈 if (result == 1) {loginCallBack.success(user); } else { loginCallBack.fail(result); } } }

最后,完成Controller:
/** * Author:ProdigalWang * Time: 2016/9/26 */ public class LoginController implements View.OnClickListener {private LoginView loginView; private ILoginModel iLoginModel; public LoginController( LoginView loginView){ this.loginView=loginView; iLoginModel=new LoginModelImpl(); } @Override public void onClick(View v) { switch (v.getId()){ case R.id.bt_login_mvc: String username=loginView.getName(); String pwd=loginView.getPwd(); if (TextUtils.isEmpty(username)){ loginView.userNameEpty(); break; } if (TextUtils.isEmpty(pwd)){ loginView.passWordEpty(); break; } //调用模型层去处理具体的请求 iLoginModel.login(username, pwd, new LoginCallBack() { @Override public void success(User user) { loginView.loginSuccess(); }@Override public void fail(int status) { if (status==0){ //模型层完成数据处理后,通知视图层做出相应的改变。用户得到反馈。 loginView.passWordError(); }else if (status==-1){ loginView.userNameError(); }else { loginView.loginFailure(); } }}); break; } } }

那么,我们实现了MVC框架模式后,我们的Activity里的代码又变成怎么样了呢?
** * 此时Activity就变为了承载视图层的容器。 */ public class MvcLoginActivity extends AppCompatActivity {private MyDataBaseHelper myDataBaseHelper; private SQLiteDatabase db; private LoginView loginView; private LoginController loginController; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_mvc_login); //初始化一个本地用户用来模拟登陆。 myDataBaseHelper = new MyDataBaseHelper(this, "Login.db", null, 1); db = myDataBaseHelper.getWritableDatabase(); //myDataBaseHelper.initData(db); MVC(); }private void MVC(){ //控件初始化和绑定 loginView= (LoginView) findViewById(R.id.activity_login_mvc); loginView.initView(); loginController=new LoginController(loginView); //视图层结合控制层 loginView.setOnclikLister(loginController); } }

没错,这个时候activity里面的代码就是如此的少。关键之处的代码注释写了,这里就不做详细解释了。
那么,来总结一下整个流程:首先用户打开应用,loginView.initView()调用,显示整个布局。这时候用户输入用户名名和密码后点击登录按钮,Controller层通过View层的getName()和getPwd()获取到用户输入的数据,紧接着Controller层会调用Model的接口中的login()方法,将数据传递给Model层进行具体的处理。当Model完成处理后,会通过LoginCallBack回调处理的结果,并通知View层进行视图的改变,这是用户得到反馈结果。
最后,总结一下MVC带来的好处与不足  :
好处:1.总所周知,采用各种各种框架模式都是为了实现高内聚低耦合,实现分层能够实现良好的分工合作,各层独立,修改哪一层对其他层的影响都能降低很多。
2.重用性高,由于模型返回的数据没有进行格式化,所以同样的构件能被不同的界面使用。例如,很多数据可能用html来表示,但是也有可能用WAP来表示,而这些表示所需要的命令是改变视图层的实现方式,而控制层和模型层无需做任何改变。
3.维护性高,部署快。不同的开发人员只需要专注于一层的实现。
  不足之处:1.不适于小型程序,如果我们在小程序上为了实现MVC框架模式而实现的话,会浪费大量不必要的时间和精力。
2.增加系统结构和实现的复杂性等。
参考资料:
1.http://baike.baidu.com/link?url=3hzUtpjpvrAJCJwjQ1OlGZZVU7Ri_7cXK0gZSqZf-IuR7sRpNRruaG6TtpV3tgJNWQ6l4YR4N6pyk99j3TX9Y2aj1yBAb837M2cLMK5J5MUEBCyjzmVOhT_3Q2_HDPMv
【小试Android中使用MVC框架模式】2.https://github.com/jpush/jchat-android

    推荐阅读