[荐]JavaMe 编程连载(3) - 也说MVC设计模式

【更新】

2012-6-6,感觉UIController.java中,handleEvent处理函数开关分支太多,能否去掉开关语句?欢迎提出比较好的重构建议。

2012-5-19,添加UML类图

【问题描述】介绍设计模式的文章和书很多,但只有使用时,才能理解设计模式的妙处。接上一篇《JavaMe连载(2)-低级界面绘图之菜单》,本文一则对UIController作出解释,一则将自己理解的MVC设计模式,结合实例,与大家交流学习。

【理论】什么是MVC?

MVC就是模型(model)、视图(view)和控制(control)。什么是模型呢?本例中,模型就是对数据使用时的封装。视图很容易理解,那就是显示内容的具体表示。控制呢?有很多人对视图和控制分不清。在本例中,控制包含视图控制器以及方法的封装。

【实例】

1 先看工程结构,如图1所示。

图1 工程结构

工程中将用户数据单独封装,作为model。供控制器和视图调用。将显示页面单独封装,作为视图。将视图控制器UIController和常用方法封装为util。UIController就是控制。

2 UML图(后续更新时补充)

 

图2 UML类图

先看代码,再分析工作机理

【代码清单】

MainMidlet.java

package com.token.midlet;

import java.io.IOException;

import javax.microedition.lcdui.*;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
import com.token.util.UIController;

public class MainMidlet extends MIDlet {
	
	private Display display;
	private static UIController controller;
	public MainMidlet() {
		// TODO Auto-generated constructor stub
		super();
		display=Display.getDisplay(this);
		
	}

	/* (non-Javadoc)
	 * @see javax.microedition.midlet.MIDlet#pauseApp()
	 */
	protected void startApp() throws MIDletStateChangeException {
		controller=new UIController(this);
		try {
			controller.init();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}//初始化RecordStore
	}

	/* (non-Javadoc)
	 * @see javax.microedition.midlet.MIDlet#pauseApp()
	 */
	protected void pauseApp() {
		this.notifyPaused();
	}

	/* (non-Javadoc)
	 * @see javax.microedition.midlet.MIDlet#destroyApp(boolean)
	 */
	protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
		controller=null;
		
	}
	
	public void setCurrent(Displayable disp){
		display.setCurrent(disp);
	}
	
	public void setCurrent(Alert alert, Displayable disp){
		display.setCurrent(alert, disp);
    }
	public Displayable getCurrent(){
		return display.getCurrent();
    }
	
	public void exit(boolean arg0){
		try{
			destroyApp(arg0);
			notifyDestroyed();
		}catch(MIDletStateChangeException e){
			//
		}
	}

}


模型(Model)

UserDataItem.java

package com.token.model;

import com.token.util.StringDealMethod;

public class UserDataItem {
	private int id;
    public String name = null;
    public String passwd = null;

    public UserDataItem(String name,String passwd)
    {
    	this.name = name;
    	this.passwd = passwd;	
    }
    
    public UserDataItem(int id,byte[] data){
        this.id=id;
    	String temp=new String(data);
    	String temp_sub[] = StringDealMethod.split(temp, ",");
    	this.name = temp_sub[0];
    	this.passwd = temp_sub[1];
    }
    
    public int getId(){
    	return id;
    }
    
    public void setId(int id){
    	this.id=id;
    }
    
    public String getName(){
        return name;
    }
    
    public void setName(String name){
        this.name = name;
    }
    
    public String getPasswd(){
        return passwd;
    }
    
    public void setPasswd(String passwd){
        this.passwd = passwd;
    }
    
    public byte[] getBytes(){
        String temp=null;
        
        if(name==null||passwd==null){
            return null;
        }else{
            temp=name+","+passwd;
        }
        
        return temp.getBytes();
    }
}


 

控制(control)

UIController.java

package com.token.util;

import java.io.IOException;

import javax.microedition.lcdui.*;

import com.token.midlet.MainMidlet;
import com.token.model.*;
import com.token.view.*;
//import com.token.view.components.Color;

public class UIController {

	private MainMidlet midlet;
	
	private TokenDataRecord tokenRecord;
	
	private WelcomeScreen welcomeScreen;
	private UserRegist reg;	
	private ActiveScreen activeScreen;
	private MainScreen mainScreen;
	private GenPasswd gen;
	private CheckScreen check;
	private ViewToken viewToken;
	private UserManage manage;
	private ShowHelp help;
	private UserAuth auth;
	private PopUpTextBox textBox;
	
	int id = 1;
	
	public UIController(MainMidlet midlet)
	{
		this.midlet = midlet;
		
		tokenRecord = new TokenDataRecord();
	}
	
	public void init() throws IOException{
		
		try {
			SplashScreen splashScreen = new SplashScreen();
			setCurrent(splashScreen);
			Thread.sleep(1000);
			
			Configure.configureColor();
			initObject();	
			
			//tokenRecord.db_deleteAllRecord();
			if(tokenRecord.db_getRecord(1)==null)
			{
				//System.out.println("add");
				ChaosMethods method = new ChaosMethods();
				TokenDataItem tokenItem = new TokenDataItem(1,(method.ChaosInitCode()+",false").getBytes());
				id=tokenRecord.db_addRecord(tokenItem);
			}
			
			//System.out.println(id);
			TokenDataItem tokenItem1 = tokenRecord.db_getRecord(id);
			//System.out.println(tokenItem1.token+","+tokenItem1.isActive);
			
			if(tokenItem1.getStatus().equals("false"))
			{
				this.handleEvent(UIController.EventID.EVENT_NEXT_WELCOME_SCREEN,null);
			}else
			{
				String flag = "0";
				Object [] args = {flag,""};
				this.handleEvent(UIController.EventID.EVENT_MAIN_SCREEN,args);
			}
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	private void initObject()
	{
		welcomeScreen = new WelcomeScreen(this);
		reg= new UserRegist(this);
		activeScreen = new ActiveScreen(this);
		...
		textBox = new PopUpTextBox(this,"输入文本","", 1000, TextField.ANY);
	}
	
	//getMethod
	public void setCurrent(Displayable disp){
		midlet.setCurrent(disp);
    }
	public void setCurrent(Alert alert, Displayable disp){
		midlet.setCurrent(alert, disp);
    }
	
	//定义事件ID内部类
    public static class EventID{
        private EventID(){
        }
        
        public static final byte EVENT_EXIT = 0;//退出
        public static final byte EVENT_NEXT_WELCOME_SCREEN = 1;//欢迎界面
        public static final byte EVENT_NEXT_USER_REGIST_SCREEN = 2;//用户注册
        public static final byte EVENT_USER_REGIST_EDIT = 3;//用户注册编辑
        public static final byte EVENT_USER_REGIST_EDIT_BACK = 4;//用户注册编辑返回
        public static final byte EVENT_NEXT_ACTIVE_SCREEN = 5;
	   //...
    }
    
    //事件处理
    public void handleEvent( int eventID, Object[] args)
    {
    	switch (eventID)
        {   
    	    case EventID.EVENT_EXIT:
    	    {
    	    	midlet.exit(false);
    	    	break;
    	    }
    	    case EventID.EVENT_NEXT_WELCOME_SCREEN:
    	    {
    	    		welcomeScreen.show();
				midlet.setCurrent(welcomeScreen);
				break;
    	    }
    	    case EventID.EVENT_NEXT_USER_REGIST_SCREEN:
    	    case EventID.EVENT_USER_REGIST_EDIT_BACK:
    	    {
    	    	reg.show(args);
    	    	Thread thread = new Thread(reg);
    	    	thread.start();
    	    	midlet.setCurrent(reg);
    	    	break;
    	    }
    	    case EventID.EVENT_USER_REGIST_EDIT:
    	    {
    	    	textBox.init(args);
    	    	midlet.setCurrent(textBox);
    	    	break;
    	    }
    	    case EventID.EVENT_NEXT_ACTIVE_SCREEN:
    	    {
    	    	activeScreen.show(args);
    	    	Thread thread = new Thread(activeScreen);
    	    	thread.start();
    	    	midlet.setCurrent(activeScreen);
    	    	break;
    	    }
    	    //...
         	default:
         	    break;
        }
    }
}

 

UserDataRecord.java

package com.token.util;

import java.util.Vector;

import javax.microedition.rms.RecordComparator;
import javax.microedition.rms.RecordEnumeration;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;

import com.token.model.*;

public class UserDataRecord {
	private static final String RECORDSTORE_NAME="USER_DB";
	private static RecordStore info;
	
	public UserDataRecord(){
	}
	
	//打开RecordStore,没有则创建
    public void openDataBase() {
        try {
            info = RecordStore.openRecordStore(RECORDSTORE_NAME, true);
        }catch (RecordStoreException ex) {            
            info =null;
        }
    }
    //关闭RecordStore
    public void closeDataBase() {
        if (info!= null) {
            try {
                info.closeRecordStore();
                info=null;
            } catch (RecordStoreException ex) {}
        }
    }
    //增加记录
    public int db_addRecord(UserDataItem item) {
                   
                try {
                    this.openDataBase();
                    byte[] data=item.getBytes();
                    int id=info.getNextRecordID();
                	info.addRecord(data,0,data.length);
                	this.closeDataBase();
                	return id;
                } catch (RecordStoreException ex) { }
        
        return -1;
    }
    //更新记录
    public void db_updateRecord(UserDataItem item){

            try {
            	this.openDataBase();      
                byte[] data=item.getBytes();
            	info.setRecord(item.getId(),data,0,data.length);
            	this.closeDataBase();
            } catch (RecordStoreException ex) { }
    }
    //访问一条记录
    public UserDataItem db_getRecord(int id){
    	UserDataItem item=null;

            try {
                this.openDataBase();
            	item = new UserDataItem(id,info.getRecord(id));
            	this.closeDataBase();
            } catch (RecordStoreException ex) { }

         return item;
    }
    //删除一条记录
    public void db_deleteRecord(int id){
            try {
                this.openDataBase();
            	info.deleteRecord(id);
            	this.closeDataBase();
            } catch (RecordStoreException ex) {}
    }
    
    //删除所有记录
    public void db_deleteAllRecord(){
            try {
            	RecordStore.deleteRecordStore(RECORDSTORE_NAME);
            } catch (RecordStoreException ex) {}
    }
    
    //访问所有记录
    public Vector db_getRecords(){
        Vector items=new Vector(10,3);
        this.openDataBase();//打开RecordStore
        RecordEnumeration enum1=null;
        int ind=0;
        try{
            UserDataItem item=null;
        	enum1=info.enumerateRecords(null,new InnerComparator(),false);
            
            while(enum1.hasPreviousElement()){
            	ind=enum1.previousRecordId();
        	    item=new UserDataItem(ind,info.getRecord(ind));
            	items.addElement(item);
            }
            
        }catch(Exception ex){ex.printStackTrace();}
        finally{
        		try{
        			enum1.destroy();
        		}catch(Exception e){}
        		
        		this.closeDataBase();//关闭RecordStore
        }//end finally
    
        return items;
    }
    //一个简单的比较器
    private class InnerComparator implements RecordComparator{
        public int compare(byte[] rec1, byte[] rec2){
            if(rec1.length>rec2.length)
                return FOLLOWS;
            else if(rec1.length<rec2.length)
                return PRECEDES;
            else 
                return EQUIVALENT;
        }

    }
}


 

视图(view)
WelcomeScreen.java

package com.token.view;

import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.GameCanvas;

import com.token.util.UIController;
import com.token.util.StringDealMethod;
import com.token.view.components.*;


public class WelcomeScreen extends GameCanvas {

	private UIController controller;
	private Graphics graphics;
	private Font ft;
	private String info;
	private String info_wrap[];
	private int width;
	private int height;
	
	private Menu menu;
	private Head head;
	private BackGroud backGroud;
	
	public WelcomeScreen(UIController control) {
		// TODO Auto-generated constructor stub
		super(false);
		controller=control;
		setFullScreenMode(true);
		graphics = getGraphics();
		
		width = getWidth();
		height = getHeight();
		
		menu = new Menu(this);
		head = new Head(this);
		backGroud = new BackGroud(this);
	}

	public void show() {
		// TODO Auto-generated method stub
		//clearScreen();
		backGroud.drawBackGroud(this, graphics);
		head.drawHead(this,graphics,"");
		menu.drawMenu(this, graphics,"下一步","退出");
		drawBody();
	}
	
	public void drawBody()
	{
		ft = Font.getFont(Font.FACE_PROPORTIONAL,Font.STYLE_BOLD,Font.SIZE_LARGE);
		
		info = "欢迎使用!\n"
				+"1 MVC测试;\n"
				+"2 自动换行测试,绘制可自动识别换行的字符串。\n";
		info_wrap = StringDealMethod.format(info, width-10, ft);
		
		graphics.setColor(Color.text);
		graphics.setFont(ft);
		for(int i=0; i<info_wrap.length; i++)
		{
			graphics.drawString(info_wrap[i], 5, i * ft.getHeight()+40, Graphics.TOP|Graphics.LEFT);
		}
	}
	
	public void clearScreen()
	{
		graphics.setColor(0xff,0xff,0xff);
		graphics.fillRect(0, 0, width, height);
	}
    
	protected void keyPressed(int keycode)
	{
		switch(keycode)
		{
			case KeyID.SOFT_RIGHT:
			{
				controller.handleEvent(UIController.EventID.EVENT_EXIT,null);
				break;
			}
			case KeyID.SOFT_LEFT:
			{
				String editor = "regist_name";
				Object [] args = {"registScreen",editor, null,null,null};
				controller.handleEvent(UIController.EventID.EVENT_NEXT_USER_REGIST_SCREEN,args);
				break;
			}
			default:;
		}
	}
	
}

UserRegist.java

package com.token.view;

import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.game.GameCanvas;
import com.token.model.*;
import com.token.util.*;
import com.token.view.components.*;

public class UserRegist extends GameCanvas implements Runnable {

	private UIController controller;
	private Graphics graphics;
	
	private Font ft;
	
	private Menu menu;
	private Head head;
	private BackGroud backGroud;
	
	private UserDataRecord userRecord;

	private String title;
	
	private TextEdit textEdit_name;
	private TextEdit textEdit_passwd;
	private TextEdit textEdit_passwd_re;
	private int textEdit_name_x;
	private int textEdit_name_y;
	private int textEdit_passwd_x;
	private int textEdit_passwd_y;
	private int textEdit_passwd_re_x;
	private int textEdit_passwd_re_y;
	private int currentlySelectedIndex = 0;
	
	private String username;
	private String passwd;
	private String passwd_re;
	
	long caretBlinkDelay = 500L;
	long lastCaretBlink = 0;
	private String object_name;
	private String editor;
	private boolean cursorBlinkOn1;
	private boolean cursorBlinkOn2;
	private boolean cursorBlinkOn3;
	
	private int width;
	private int height;
	
	public UserRegist(UIController control) 
	{
		super(false);
		this.controller=control;
		this.title = "用户注册";
		setFullScreenMode(true);
		graphics = getGraphics();
		
		width = getWidth();
		height = getHeight();
		
		menu = new Menu(this);
		head = new Head(this);
		backGroud = new BackGroud(this);
		
		userRecord = new UserDataRecord();
		
		textEdit_name = new TextEdit(this);
		textEdit_passwd = new TextEdit(this);
		textEdit_passwd_re = new TextEdit(this);
	}

	public void show(Object[] args) {
		// TODO Auto-generated method stub
		setFullScreenMode(true);
		
		object_name = ((String)args[0]!=null)?(String)args[0]:"";
		editor = ((String)args[1]!=null)?(String)args[1]:"";
		username = ((String)args[2]!=null)?(String)args[2]:"";
		passwd = ((String)args[3]!=null)?(String)args[3]:"";
		passwd_re = ((String)args[4]!=null)?(String)args[4]:"";
		
		if(editor.equals("regist_name"))
		{
			cursorBlinkOn1 = true;
			cursorBlinkOn2 = false;
			cursorBlinkOn3 = false;
			currentlySelectedIndex =0;
		}
		else if(editor.equals("regist_passwd"))
		{
			cursorBlinkOn1 = false;
			cursorBlinkOn2 = true;
			cursorBlinkOn3 = false;
			currentlySelectedIndex =1;
		}
		else if(editor.equals("regist_passwd_re"))
		{
			cursorBlinkOn1 = false;
			cursorBlinkOn2 = false;
			cursorBlinkOn3 = true;
			currentlySelectedIndex =2;
		}
		
		//System.out.println(object_name);
		//System.out.println(editor);
		draw();
		redraw();
	}

	public void draw()
	{
		//clearScreen();
		backGroud.drawBackGroud(this, graphics);
		head.drawHead(this,graphics,this.title);
		menu.drawMenu(this,graphics,"下一步","退出");
		drawBody();
	}

	private void redraw()
	{
		switch(currentlySelectedIndex)
		{
			case 0:
			{
				cursorBlinkOn2 = false;
				cursorBlinkOn3 = false;
				editor = "regist_name";
				break;
			}
			case 1:
			{
				cursorBlinkOn1 = false;
				cursorBlinkOn3 = false;
				editor = "regist_passwd";
				break;
			}
			case 2:
			{
				cursorBlinkOn1 = false;
				cursorBlinkOn2 = false;
				editor = "regist_passwd_re";
				break;
			}
			default:;
		}
		
		textEdit_name.drawTextBox(this, graphics, username, textEdit_name_x, textEdit_name_y, cursorBlinkOn1);
		textEdit_passwd.drawTextBox(this, graphics, passwd, textEdit_passwd_x, textEdit_passwd_y, cursorBlinkOn2);
		textEdit_passwd.drawTextBox(this, graphics, passwd_re, textEdit_passwd_re_x, textEdit_passwd_re_y, cursorBlinkOn3);
		textEdit_name.flushGraphics();
	}

	public void drawBody()
	{
		int margin =5;
		ft = Font.getFont(Font.FACE_PROPORTIONAL,Font.STYLE_BOLD,Font.SIZE_LARGE);
		
		String info = "用户名:\n";
		String info_wrap1[] = StringDealMethod.format(info, width-10, ft);
		
		graphics.setFont(ft);
		graphics.setColor(Color.text);
		for(int i=0; i<info_wrap1.length; i++)
		{
			graphics.drawString(info_wrap1[i],5, (i) * ft.getHeight()+40, Graphics.TOP|Graphics.LEFT);
		}
		
		textEdit_name_x = 5;
		textEdit_name_y = info_wrap1.length * ft.getHeight()+40;
		textEdit_name.drawTextBox(this, graphics, username, textEdit_name_x, textEdit_name_y, cursorBlinkOn1);
		
		info = "用户密码:\n";
		String info_wrap2[] = StringDealMethod.format(info, width-10, ft);
	
		graphics.setFont(ft);
		graphics.setColor(Color.text);
		for(int i=0; i<info_wrap2.length; i++)
		{
			graphics.drawString(info_wrap2[i],5, (i+info_wrap1.length) * ft.getHeight()+textEdit_name.height+margin+40, Graphics.TOP|Graphics.LEFT);
		}
		
		textEdit_passwd_x = 5;
		textEdit_passwd_y = (info_wrap1.length+info_wrap2.length) * ft.getHeight()+textEdit_name.height+margin+40;
		textEdit_passwd.drawTextBox(this, graphics, passwd, textEdit_passwd_x, textEdit_passwd_y, cursorBlinkOn2);
	
		info = "密码确认:\n";
		String info_wrap3[] = StringDealMethod.format(info, width-10, ft);
	
		graphics.setFont(ft);
		graphics.setColor(Color.text);
		for(int i=0; i<info_wrap3.length; i++)
		{
			graphics.drawString(info_wrap3[i],5, (i+info_wrap1.length+info_wrap2.length) * ft.getHeight()+textEdit_name.height+textEdit_passwd.height+2*margin+40, Graphics.TOP|Graphics.LEFT);
		}
		
		textEdit_passwd_re_x = 5;
		textEdit_passwd_re_y = (info_wrap1.length+info_wrap2.length+info_wrap3.length) * ft.getHeight()+textEdit_name.height+textEdit_passwd.height+2*margin+40;
		textEdit_passwd_re.drawTextBox(this, graphics, passwd_re, textEdit_passwd_re_x, textEdit_passwd_re_y, cursorBlinkOn3);
	
		
	}

	public void clearScreen()
	{
		graphics.setColor(0xff,0xff,0xff);
		graphics.fillRect(0, 0, width, height);
	}

	public void checkTimeStamp()
	{
		long currentTime = System.currentTimeMillis();
		//System.out.println("1");
		if(lastCaretBlink + caretBlinkDelay < currentTime)
		{
			//System.out.println("2");
			if(editor.equals("regist_name"))
			{
				cursorBlinkOn1 =! cursorBlinkOn1;
				cursorBlinkOn2 = false;
				cursorBlinkOn3 = false;
			}
			else if(editor.equals("regist_passwd"))
			{
				cursorBlinkOn1 = false;
				cursorBlinkOn2 =! cursorBlinkOn2;
				cursorBlinkOn3 = false;
			}
			else if(editor.equals("regist_passwd_re"))
			{
				cursorBlinkOn1 = false;
				cursorBlinkOn2 = false;
				cursorBlinkOn3 =! cursorBlinkOn3;
			}
			lastCaretBlink = currentTime;
		}
	}

	public void run()
	{
		//System.out.println("run");
		while(true)
		{
			checkTimeStamp();
			
			redraw();
			try	
			{
				synchronized(this)
				{
					//System.out.println("3");
					wait(50L);
				}			
			}
			catch(Exception e)
			{
				e.printStackTrace();
			}
			
		}
	}

	protected void keyPressed(int keyCode)
	{
		switch(keyCode)
		{
			case KeyID.SOFT_RIGHT:
			{
				controller.handleEvent(UIController.EventID.EVENT_EXIT,null);
				break;
			}
			case KeyID.SOFT_LEFT:
			{
				if(username!="" && passwd!=""&&passwd_re!="")
				{
					if(passwd.equals(passwd_re))
					{
						
						
						userRecord.db_deleteAllRecord();
						if(userRecord.db_getRecord(1)==null)
						{
							UserDataItem userItem = new UserDataItem(1,(username+","+passwd).getBytes());
							userRecord.db_addRecord(userItem);
							userItem = null;
							System.gc();
						}
						
						String update = "start";
						Object [] args = {"activeScreen", null, update};
						controller.handleEvent(UIController.EventID.EVENT_NEXT_ACTIVE_SCREEN,args);
					}
				}
				break;
			}
			case KeyID.KEY_EDIT:
			case KEY_NUM0:
			case KEY_NUM1:
			case KEY_NUM2:
			case KEY_NUM3:
			case KEY_NUM4:
			case KEY_NUM5:
			case KEY_NUM6:
			case KEY_NUM7:
			case KEY_NUM8:
			case KEY_NUM9:
			{
				//System.out.println(editor);
				Object[] args = {object_name,editor,username,passwd,passwd_re};
				controller.handleEvent(UIController.EventID.EVENT_USER_REGIST_EDIT,args);
				break;
			}
			default:;
		}
			
		keyCode = getGameAction(keyCode);
		switch(keyCode)
		{
			case UP:
			case LEFT:
			{
				currentlySelectedIndex--;
				if(currentlySelectedIndex<0)
				{
					currentlySelectedIndex=0;
				}
				else
				{
					redraw();
				}
				break;
			}
			case DOWN:
			case RIGHT:
			{
				currentlySelectedIndex++;
				if(currentlySelectedIndex>2)
				{
					currentlySelectedIndex=2;
				}
				else
				{
					redraw();
				}
				
				break;
			}
		}
	}

}


*TextEdit是利用GameCanvas绘制的自定义文本编辑框。后续文章将给出具体实现。


【分析】

1 在MainMidlet调用控制器UIController,并向UIController传递midlet作为参数。

controller=new UIController(this);
try {
	controller.init();
	} catch (IOException e) {
	// TODO Auto-generated catch block
	e.printStackTrace();
    }//


2 控制器的实现是通过一个事件的机制实现的, 在UIController中,先建立一个事件ID的内部类。

public static class EventID{
        private EventID(){
        }
        
        public static final byte EVENT_EXIT = 0;//退出
        public static final byte EVENT_NEXT_WELCOME_SCREEN = 1;//欢迎界面
        public static final byte EVENT_NEXT_USER_REGIST_SCREEN = 2;//用户注册
        public static final byte EVENT_USER_REGIST_EDIT = 3;//用户注册编辑
        public static final byte EVENT_USER_REGIST_EDIT_BACK = 4;//用户注册编辑返回
        public static final byte EVENT_NEXT_ACTIVE_SCREEN = 5;
	   //...
    }


3 一次性初始化所有界面,分配内存,调用时,只是执行视图类的show方法。为什么不将初始话放在调用时进行呢?主要是因为视图类有多次重用,如果每一次调用都new(初始化,分配内存)一次,手机有限的内存很快会被用光,这是会出现一些程序自动退出的问题。

private void initObject()
{
	welcomeScreen = new WelcomeScreen(this);
	reg= new UserRegist(this);
	activeScreen = new ActiveScreen(this);
	...
	textBox = new PopUpTextBox(this,"输入文本","", 1000, TextField.ANY);
}

4 控制器对视图的处理采用状态机实现

 public void handleEvent( int eventID, Object[] args)
    {
    	switch (eventID)
        {   
    	    case EventID.EVENT_EXIT:
    	    {
    	    	midlet.exit(false);
    	    	break;
    	    }
    	    case EventID.EVENT_NEXT_WELCOME_SCREEN:
    	    {
    	    		welcomeScreen.show();
				midlet.setCurrent(welcomeScreen);
				break;
    	    }
    	    case EventID.EVENT_NEXT_USER_REGIST_SCREEN:
    	    case EventID.EVENT_USER_REGIST_EDIT_BACK:
    	    {
    	    	reg.show(args);
    	    	Thread thread = new Thread(reg);
    	    	thread.start();
    	    	midlet.setCurrent(reg);
    	    	break;
    	    }
    	    case EventID.EVENT_USER_REGIST_EDIT:
    	    {
    	    	textBox.init(args);
    	    	midlet.setCurrent(textBox);
    	    	break;
    	    }
    	    case EventID.EVENT_NEXT_ACTIVE_SCREEN:
    	    {
    	    	activeScreen.show(args);
    	    	Thread thread = new Thread(activeScreen);
    	    	thread.start();
    	    	midlet.setCurrent(activeScreen);
    	    	break;
    	    }
    	    //...
         	default:
         	    break;
        }
    }
}


5 视图类初始化时,需要将控制器作为参数初始化,以对事件做出判断。如WelcomeScreen.java中先做出如下声明:

private UIController controller;


再在构造函数中,传递控制器

public WelcomeScreen(UIController control) {
		// TODO Auto-generated constructor stub
		super(false);
		controller=control;


6 视图切换事件响应采用如下方式,在keyPressed中,对按键事件进行判断,然后调用UIController的handEvent方法。

protected void keyPressed(int keycode)
	{
		switch(keycode)
		{
			case KeyID.SOFT_RIGHT:
			{
				controller.handleEvent(UIController.EventID.EVENT_EXIT,null);
				break;
			}
			case KeyID.SOFT_LEFT:
			{
				String editor = "regist_name";
				Object [] args = {"registScreen",editor, null,null,null};
				controller.handleEvent(UIController.EventID.EVENT_NEXT_USER_REGIST_SCREEN,args);
				break;
			}
			default:;
		}
	}
	
}

 

7 控制器可以通过handEvent的args传递参数,如

String update = "start";
Object [] args = {"activeScreen", null, update};
controller.handleEvent(UIController.EventID.EVENT_NEXT_ACTIVE_SCREEN,args);

UserRegist传递了一个update变量给下一个视图。

8 在看一下模型,在UserDataItem中存储的是用户注册的信息。利用UserDataRecord类对记录进行操作。

在视图类中,通过以下方式调用:

先声明

private UserDataRecord userRecord;

构建对象

userRecord = new UserDataRecord();

使用对象

userRecord.db_deleteAllRecord();
						if(userRecord.db_getRecord(1)==null)
						{
							UserDataItem userItem = new UserDataItem(1,(username+","+passwd).getBytes());
							userRecord.db_addRecord(userItem);
							userItem = null;
							System.gc();
						}
						


9 包com.token.view.components是对视图类中使用的自定义控件的封装

 

综述,这样就实现了模型、视图、控制的分离。


 【参考文献】

(1) 万辉,王军[M]. 基于Eclipse环境的J2ME应用程序开发,清华大学出版社

(2) http://blog.csdn.net/cjjky/article/category/807008

 

 

转载请标明出处,仅供学习交流,勿用于商业目的

Copyright @ http://blog.csdn.net/tandesir

 

 

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值