您的位置:首页 > 职场人生

最老程序员创业开发实训10---Android---注册登录功能实现1

2015-09-17 12:05 916 查看
用户在观看完应用介绍页面之后,会点击进入应用按钮,这时由于用户是第一次运行,所以会弹出注册页面。如果是老用户,启动应用时,在Splash页面之后,如果应用记录着用户的登录信息,测直接进入主页面,如果从本地取不到用户登录信息,则将显示登录页面。
注册和登录功能看起来很简单,但是由于我们这里需要实现一个完整的应用支撑基础设施,因此需要分几个部分来进行。我们首先会讨论怎样创建并使用Activity中会用到的Model类,在这中间我们会采用Application对象作为中心信息仓库,每个Model类只是中心信息仓库的视图,便于对应的Activity类来使用;接着我们会讨论Activity类的基类,在其中包装诸如按回退键提示退出等功能;接着我们会讨论网络请求的实现,这里我们采用异步任务的方式来进行,协议采用Json Over Http,因此会顺便介绍Json的解析。
在进入正文之前,首先解释一个问题,我们什么时候检查版本更新。一般你可以在很多点来检查版本更新,我在这里采用进入主页面前检查版本更新,为什么这样做呢?因为在实际项目中,我们可能会有些小范围测试的版本,我们会采用灰度更新的机制,即只有一部分用户会收到更新通知,试用最新版本,如果反响很好,我们再向普通用户推出版本更新,因此检查版本更新放在了登录之后。
好了,我们先来看怎样实现MVC中的Model。我们首先在WkyLib工程中,定义Model的基类WkyModel,代码如下所示:

public class WkyModel {
	public static WkyModel getInstance(String objectId, Class cls) {
		if (models.containsKey(objectId)) {
			return models.get(objectId);
		}
		WkyModel model = (WkyModel)WkyReflection.callPrivateConstructor(cls);
		model.setObjectId(objectId);
		Log.e("wky", "cls:" + cls.getCanonicalName() + "!");
		if (null == model) {
			model = new WkyModel();
		}
		models.put(objectId, model);
		return model;
	}
	
	public static void removeObject(String objectId) {
		models.remove(objectId);
	}
	
	public static void removeInstance(String objectId) {
		models.remove(objectId);
	}
	

	/**
	 * 在Activity.onDestroy中调用,判断是否需要将实例从models中移除
	 * @return
	 * 【闫涛 2015.09.17】初始版本
	 */
	public boolean isShared() {
		return isShared;
	}

	/**
	 * 如果想要在多个界面中使用同一个Model对象,则需要调用此函数,
	 * 将isShared设置为true,这时在Activity.onDestroy中就不会将本实例从models中移除了
	 * @param isShared
	 * 【闫涛 2015.09.17】初始版本
	 */
	public void setShared(boolean isShared) {
		this.isShared = isShared;
	}

	public String getObjectId() {
		return objectId;
	}

	public void setObjectId(String objectId) {
		this.objectId = objectId;
	}

	private static HashMap<String, WkyModel> models = new HashMap<String, WkyModel>();
	protected boolean isShared = false;
	protected String objectId = null;
}

假设一个Activity有对应的Model类时,例如JysRegisgetrLoginActivity需要JysRegisterLoginModel类对象时,会通过调用getInstance方法来获取实例。每个Model类,可以同时存在多个实例,保存在models属性中。一般情况下,Activity在onCreate或在启动此Activity时,会生成一个Model类的实例,当该Activity退出时,在onDestroy回调函数中将该实例从models属性中移除。但是如果设置了isShared为ture时,则onDestroy方法中就不会移除此对象,就可以在不同的Activity实例中使用了。
在上面的代码中,我们用到了Java的反射机制,根据getInstance方法第二个参数的类,调用该类的私有无参数构造函数,生成该类的对象,我们引入了一个反射工具类WkyReflection,代码如下所示:

public class WkyReflection {
	/**
	 * 调用类的私有无参数构造函数,生成该类对象并返回该对角
	 * 例子:
	 * WkyRegisterLoginModel model = (WkyRegisterLoginModel)WkyReflection.callPrivateConstructor(WkyRegisterLoginModel.class);
	 * @param cls
	 * @return
	 * 【闫涛 2015.09.17】初始版本
	 */
	public static Object callPrivateConstructor(Class cls) {
		Constructor[] constructor = cls.getDeclaredConstructors();
		constructor[0].setAccessible(true);
		Object rst = null;
		try {
			rst = constructor[0].newInstance();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return rst; 
	}
}

在本节开头我们就提到,我们的信息保存在应用的中心信息仓库中,每个Model里保存的,只是其中的一部分,在Android平台下,我们可以利用Application子类来作为中心信息仓库,代码如下所示:

/**
	 * model类将所有信息均保存在HashMap中,这样信息可以在Model之间共用
	 * @param key
	 * @param val
	 * 【闫涛 2015.09.17】初始版本
	 */
	public static void putObject(String key, Object val) {
		params.put(key, val);
	}
	
	/**
	 * 从HashMap中取出相应的信息,调用者需要将其转化为正确的类
	 * @param key
	 * @return
	 * 【闫涛 2015.09.17】初始版本
	 */
	public static Object getObject(String key) {
		return params.get(key);
	}
	
	public void exitApp() {
		System.exit(1);
	}
	
	public static WkyApplication instance = null;
	private static HashMap<String, Object> params = new HashMap<String, Object>();

下面我们来看注册登录的基类WkyRegisterLoginModel类的实现:

public class WkyRegisterLoginModel extends WkyModel {
	
	protected WkyRegisterLoginModel() {
		WkyApplication.putObject(WkyConstants.ROLE_ID, Integer.valueOf(WkyConstants.ROLE_JYS));
		WkyApplication.putObject(WkyConstants.REGISTER_LOGIN_STATE, Integer.valueOf(STATE_LOGIN));
		roleId = (Integer)WkyApplication.getObject(WkyConstants.ROLE_ID);
		state = (Integer)WkyApplication.getObject(WkyConstants.REGISTER_LOGIN_STATE);
	}
	
	
	public int getState() {
		return state;
	}
	public void setState(int state) {
		this.state = state;
	}

	public int getRoleId() {
		return roleId;
	}

	public void setRoleId(int roleId) {
		this.roleId = roleId;
	}

	public final static int STATE_REGISTER = 1;
	public final static int STATE_LOGIN = 2;
	public final static int STATE_FORGET_PWD = 3;
	public final static int STATE_ACTIVATE = 4;

	private int state = STATE_LOGIN;
	private int roleId = WkyConstants.ROLE_JYS;
}
在上面的代码中,里面有两个属性比较重要,第一个state代表注册登录Activity所处的状态,一共有四种:注册、登录、忘记密码、激活,第二个属性roleId代表用户的角色,可以是基因师也可以是大众。需要注意的是,在构造函数中,这两个属性的值是存到中心信息仓库中的。
下面看具体应用WkgJys中,怎样定义具体的Model类JysRegisterLoginModel:

public class JysRegisterLoginModel extends WkyRegisterLoginModel {
	protected JysRegisterLoginModel() {
		super();
		isShared = false;
	}
}
在这里,由于没有特别的需要,没有定义新的属性,因此代码很简单。但是需要注意的是isShared = false,意味着在onDestroy方法中,这个实例将被移除,不会被共享。
好了,有了上述代码,Model体系就创建完成了。在下一节中,我们将讲到怎样实现MVC中的C,即Activity的实现方式。

华丽的分隔线
******************************************************************************************************************************************************************************
希望大家多支持,有大家的支持,我才能走得更远,谢谢!
银行账号:622202 0200 1078 56128 闫涛
我的支付宝:yt7589@hotmail.com
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: