现在的位置: 首页 > 综合 > 正文

Antrus – 我搞的一个Android下的MVC开源框架

2013年03月03日 ⁄ 综合 ⁄ 共 5251字 ⁄ 字号 评论关闭

Antrus – 我搞的一个Android下的MVC开源框架

(开源地址:http://code.google.com/p/antrus/)

蒋彪@南京 2011-6-20

1.     前言

   做了几个Android项目,感触颇深。特别对我这种J2EE程序员,Android下的东西有点类似于swing。

  到处都是冗余的代码,死板的设计,层次之间的紧密耦合,大量的无用功被浪费在重头造轮子。

   至此危难之际,我真的是非常怀念过去的J2EE的时代。Struts,Spring,Hiebernate,到处都是大师级的框架,清晰的分层。。。。

    周末的时候,我在想,能不能在Android下应用struts的思想,做一个结构清晰,分层合理的架构呢。

   一 做起来就不可收拾,越做越感觉到框架和分层的力量。

2.     框架的构思

Android一个大问题就是显示层和控制层没有解耦,大量的逻辑代码被写在Activity中。所以我首先想到的就是将View和控制层分开。

所以,首先,我把Activity抽象出来一个BaseController,部分的代码如下:

在这个代码中,我把画面初期化封装到BaseController中来实现,给画面增加按钮事件也封装在其中,画面的跳转也封装在其中。

 

  1. import android.app.Activity;  
  2. import android.app.Dialog;  
  3. import android.app.ProgressDialog;  
  4. import android.content.Intent;  
  5. import android.content.pm.PackageInfo;  
  6. import android.content.pm.PackageManager;  
  7. import android.os.Bundle;  
  8. import android.view.Menu;  
  9. import android.view.MenuItem;  
  10. import android.view.Window;  
  11.   
  12. /** 
  13.  * 实现对Active的包装,包装成控制器 
  14.  *  
  15.  * @author jiangbiao 
  16.  *  
  17.  */  
  18. public class BaseController extends Activity {  
  19. @Override  
  20.     protected final void onCreate(Bundle savedInstanceState) {  
  21.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  22.   
  23.         onBeforeCreate(savedInstanceState);  
  24.         super.onCreate(savedInstanceState);  
  25.   
  26.         onCreateContent(savedInstanceState);  
  27.         onAfterCreate(savedInstanceState);  
  28.     }  
  29. /** 
  30.      * 画面初期化之前的处理 
  31.      *  
  32.      * @param savedInstanceState 
  33.      */  
  34.     protected void onBeforeCreate(Bundle savedInstanceState) {  
  35.     }  
  36.   
  37.     /** 
  38.      * 画面初期化之后的处理 
  39.      *  
  40.      * @param savedInstanceState 
  41.      */  
  42.     protected void onAfterCreate(Bundle savedInstanceState) {  
  43.         addViewAction();  
  44.     }  
  45.   
  46.     /** 
  47.      * 给按钮增加事件 
  48.      */  
  49.     public void addViewAction(){  
  50.           
  51.     }  
  52.       
  53.     /** 
  54.      * 实现画面的跳转 
  55.      * @next 跳转目的地 
  56.      * @param 参数Form 
  57.      */  
  58.     public void dropToNextController(BaseController next, Form param){  
  59.         Intent intent = new Intent();  
  60.         Bundle bundle = new Bundle();  
  61.         bundle.putSerializable("param", param);  
  62.         intent.putExtras(bundle);  
  63.         intent.setClass(this, next.getClass());  
  64.         startActivity(intent);  
  65.     }  
  66.       
  67.       
  68.     /** 
  69.      * 画面的初期化 
  70.      *  
  71.      * @param savedInstanceState 
  72.      * @throws ClassNotFoundException 
  73.      * @throws NoSuchFieldException 
  74.      * @throws SecurityException 
  75.      * @throws IllegalAccessException 
  76.      * @throws IllegalArgumentException 
  77.      */  
  78.     protected void onCreateContent(Bundle savedInstanceState) {  
  79.         try {  
  80.             PackageManager manager = this.getPackageManager();  
  81.             PackageInfo info = manager.getPackageInfo(this.getPackageName(), 0);  
  82.             packageName = info.packageName;  //包名  
  83.             Class<?> c = Class.forName( packageName + ".R$layout");  
  84.             Field f;  
  85.             XMLName = XMLName.substring(XMLName.lastIndexOf(".") + 1);  
  86.             f = c.getDeclaredField(XMLName);  
  87.             mainView = f.getInt(null);  
  88.             setContentView(mainView);  
  89.         } catch (Exception e) {  
  90.             Logger.i(TAG, "onCreateContent error : " + e.getMessage());  
  91.         }  
  92.     }  
  93. @Override  
  94.     protected Dialog onCreateDialog(int id) {  
  95.         switch (id) {  
  96.         case DIALOG_ID_PROGRESS_DEFAULT:  
  97.             ProgressDialog dlg = new ProgressDialog(this);  
  98.             dlg.setMessage("Working...");  
  99.             dlg.setCancelable(true);  
  100.             return dlg;  
  101.         default:  
  102.             return super.onCreateDialog(id);  
  103.   
  104.         }  
  105.     }  
  106.   
  107. }  

接着,我按着struts的思路来,封装了一个form,实现序列化接口。这样,就能把画面上所有的参数封装到对应的form中去。

 

  1. /** 
  2.  * 将画面上所有的参数都封装到Form中 
  3.  *  
  4.  * @author jiangbiao 
  5.  *  
  6.  */  
  7. public abstract class Form implements Serializable {  
  8.   
  9.     //用来存放当前Form的ID  
  10.     private String tag;  
  11.   
  12.     public String getTag() {  
  13.         return tag;  
  14.     }  
  15.   
  16.     public void setTag(String tag) {  
  17.         this.tag = tag;  
  18.     }  
  19.   
  20.     public int getTargetActivityID() {  
  21.         return targetActivityID;  
  22.     }  
  23.   
  24.     public void setTargetActivityID(int targetActivityID) {  
  25.         this.targetActivityID = targetActivityID;  
  26.     }  
  27.   
  28.     //用来存放跳转之后的画面ID  
  29.     private int targetActivityID;  
  30. }  

这样,android就变成:

XML ------ 传值(form)------- >Controller A------ >   Controller B

 

 

怎么样,是不是有点struts的雏形?

 

3.     框架的一个小实践

光说没用,任何一个技术框架都要经得起实践的考验。

来,让我们看看anstrus能干什么

我们就实现一个小小的登录画面,前台的XML文件还是照着原样子写,代码Activity。。。

 

  1. public class Login extends BaseController {  
  2.       
  3.     public void addViewAction(){  
  4.         Button btn = (Button) findViewById(R.id.loginBtn);  
  5.   
  6.         btn.setOnClickListener(new OnClickListener()  
  7.         {  
  8.             public void onClick(View v)  
  9.             {  
  10.                 //将画面上的数值封装成Form  
  11.                 //TODO 未来考虑用配置文件来代替代码中的path  
  12.                 LoginForm request = (LoginForm)FormsFactory.createForms("com.hyronjs.jiangbiao.LoginForm", Login.this);  
  13.                   
  14.                 //这里可以调用Logic然后做一系列处理  
  15.                   
  16.                 //执行画面跳转  
  17.                 dropToNextController(Login.this, request);  
  18.             }  
  19.         });  
  20.     }  
  21. }  

看到了没有,基本的功能都实现了,但是代码变得无比精巧。。。

 

4.     Anstrus的路线图

  当然,这玩意现在还不足以工业化应用。

但是,有了开始,还怕没有结果吗。

我考虑在未来在这个玩意下加上更多的功能:

1.       第一步

引入XML配置文件,彻底解耦View和Controller

2.       第二步

引入POJO技术,在form里用注释的方法来编写check条件。   

3.       第三步

引入spring机制,封装一系列可重用的service。在此之上封装更多的业务应用。

#以上#

 

抱歉!评论已关闭.