蒋彪@南京 2011-6-20
1. 前言
做了几个Android项目,感触颇深。特别对我这种J2EE程序员,Android下的东西有点类似于swing。
到处都是冗余的代码,死板的设计,层次之间的紧密耦合,大量的无用功被浪费在重头造轮子。
至此危难之际,我真的是非常怀念过去的J2EE的时代。Struts,Spring,Hiebernate,到处都是大师级的框架,清晰的分层。。。。
周末的时候,我在想,能不能在Android下应用struts的思想,做一个结构清晰,分层合理的架构呢。
一 做起来就不可收拾,越做越感觉到框架和分层的力量。
2. 框架的构思
Android一个大问题就是显示层和控制层没有解耦,大量的逻辑代码被写在Activity中。所以我首先想到的就是将View和控制层分开。
所以,首先,我把Activity抽象出来一个BaseController,部分的代码如下:
在这个代码中,我把画面初期化封装到BaseController中来实现,给画面增加按钮事件也封装在其中,画面的跳转也封装在其中。
- import android.app.Activity;
- import android.app.Dialog;
- import android.app.ProgressDialog;
- import android.content.Intent;
- import android.content.pm.PackageInfo;
- import android.content.pm.PackageManager;
- import android.os.Bundle;
- import android.view.Menu;
- import android.view.MenuItem;
- import android.view.Window;
- /**
- * 实现对Active的包装,包装成控制器
- *
- * @author jiangbiao
- *
- */
- public class BaseController extends Activity {
- @Override
- protected final void onCreate(Bundle savedInstanceState) {
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- onBeforeCreate(savedInstanceState);
- super.onCreate(savedInstanceState);
- onCreateContent(savedInstanceState);
- onAfterCreate(savedInstanceState);
- }
- /**
- * 画面初期化之前的处理
- *
- * @param savedInstanceState
- */
- protected void onBeforeCreate(Bundle savedInstanceState) {
- }
- /**
- * 画面初期化之后的处理
- *
- * @param savedInstanceState
- */
- protected void onAfterCreate(Bundle savedInstanceState) {
- addViewAction();
- }
- /**
- * 给按钮增加事件
- */
- public void addViewAction(){
- }
- /**
- * 实现画面的跳转
- * @next 跳转目的地
- * @param 参数Form
- */
- public void dropToNextController(BaseController next, Form param){
- Intent intent = new Intent();
- Bundle bundle = new Bundle();
- bundle.putSerializable("param", param);
- intent.putExtras(bundle);
- intent.setClass(this, next.getClass());
- startActivity(intent);
- }
- /**
- * 画面的初期化
- *
- * @param savedInstanceState
- * @throws ClassNotFoundException
- * @throws NoSuchFieldException
- * @throws SecurityException
- * @throws IllegalAccessException
- * @throws IllegalArgumentException
- */
- protected void onCreateContent(Bundle savedInstanceState) {
- try {
- PackageManager manager = this.getPackageManager();
- PackageInfo info = manager.getPackageInfo(this.getPackageName(), 0);
- packageName = info.packageName; //包名
- Class<?> c = Class.forName( packageName + ".R$layout");
- Field f;
- XMLName = XMLName.substring(XMLName.lastIndexOf(".") + 1);
- f = c.getDeclaredField(XMLName);
- mainView = f.getInt(null);
- setContentView(mainView);
- } catch (Exception e) {
- Logger.i(TAG, "onCreateContent error : " + e.getMessage());
- }
- }
- @Override
- protected Dialog onCreateDialog(int id) {
- switch (id) {
- case DIALOG_ID_PROGRESS_DEFAULT:
- ProgressDialog dlg = new ProgressDialog(this);
- dlg.setMessage("Working...");
- dlg.setCancelable(true);
- return dlg;
- default:
- return super.onCreateDialog(id);
- }
- }
- }
接着,我按着struts的思路来,封装了一个form,实现序列化接口。这样,就能把画面上所有的参数封装到对应的form中去。
- /**
- * 将画面上所有的参数都封装到Form中
- *
- * @author jiangbiao
- *
- */
- public abstract class Form implements Serializable {
- //用来存放当前Form的ID
- private String tag;
- public String getTag() {
- return tag;
- }
- public void setTag(String tag) {
- this.tag = tag;
- }
- public int getTargetActivityID() {
- return targetActivityID;
- }
- public void setTargetActivityID(int targetActivityID) {
- this.targetActivityID = targetActivityID;
- }
- //用来存放跳转之后的画面ID
- private int targetActivityID;
- }
这样,android就变成:
XML ------ 传值(form)------- >Controller A------ > Controller B
怎么样,是不是有点struts的雏形?
3. 框架的一个小实践
光说没用,任何一个技术框架都要经得起实践的考验。
来,让我们看看anstrus能干什么
我们就实现一个小小的登录画面,前台的XML文件还是照着原样子写,代码Activity。。。
- public class Login extends BaseController {
- public void addViewAction(){
- Button btn = (Button) findViewById(R.id.loginBtn);
- btn.setOnClickListener(new OnClickListener()
- {
- public void onClick(View v)
- {
- //将画面上的数值封装成Form
- //TODO 未来考虑用配置文件来代替代码中的path
- LoginForm request = (LoginForm)FormsFactory.createForms("com.hyronjs.jiangbiao.LoginForm", Login.this);
- //这里可以调用Logic然后做一系列处理
- //执行画面跳转
- dropToNextController(Login.this, request);
- }
- });
- }
- }
看到了没有,基本的功能都实现了,但是代码变得无比精巧。。。
4. Anstrus的路线图
当然,这玩意现在还不足以工业化应用。
但是,有了开始,还怕没有结果吗。
我考虑在未来在这个玩意下加上更多的功能:
1. 第一步
引入XML配置文件,彻底解耦View和Controller
2. 第二步
引入POJO技术,在form里用注释的方法来编写check条件。
3. 第三步
引入spring机制,封装一系列可重用的service。在此之上封装更多的业务应用。
#以上#