最老程序员创业开发实训12---Android---在MVC架构下Activity设计及实现

在上一节中,我们讲述了如何在Android平台下,以MVC架构为指导,实现模型类的方法。在本节中,我们要重点讨论一下,怎样设计Activity类,作为MVC中的控制器,并在其中使用我们在上节所讲述的模型类。在这里我们只讨论重要的代码,对于资源文件及Activity页面设计及实现细节,由于篇幅所限,就只能略过了,大家可以在稍后公布的项目下载包中查看相应的代码。

我们以具体项目WkgJys项目为例,项目在首次运行时,Splash页面之后,会进入JysAppTourActivity,在看完所有介绍页面之后,点击进入应用按钮,由于是程序第一次运行,为进入JysRegisterLoginActivity对应的页面,并且状态为注册状态。我们就从这里开始讨论。

首先,有一些公共功能,如按回退键提示用户是否退出系统等功能,我们需要定义一个项目中所有Activity的基类WkyActivity,代码如下所示:

/**
 * 所有Activity的基类
 * @author 闫涛 2015.09.18
 *
 */
public class WkyActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE); // 不显示TitleBar
        // 连屏幕上的状态栏也不显示
        //getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        // 在manifest文件中对每个activity android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
        handler = new Handler();
    }

    /**
     * Activity在onCreate时会初始化其对应的Model类,因此在销毁时也需要移除该对象
     * 【闫涛 2015.09.17】初始版本
     */
	@Override
	public void onDestroy() {
		super.onDestroy();
		if (!model.isShared()) {
			WkyModel.removeObject(model.getObjectId());
		}
	}

	/**
	 * 用户点击回退按钮时,提示用户是否退出应用,如果选择确定,则退出应用
	 * 【闫涛 2015.09.18】实始版本
	 */
	@Override
	public void onBackPressed() {
		new AlertDialog.Builder(this).setTitle("确定退出吗?")
		.setNeutralButton("确定", new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
				System.exit(1);
				//myApplication.closeApp();
			}
		})
		.setNegativeButton("取消", new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
				dialog.cancel();
			}
		}).show();
	}

    protected Handler handler = null; // 用于响应消息总线

	protected WkyModel model = null;
	protected Activity thisActivity = null;
}

在上面的代码中,提醒大家注意handler属性,这是为了后面将要讨论到的消息总线机制设计的。如果某些Activity需要响应消息总线上的消息,就需要将该handler注册到消息总线上去,这部分内容我们会在以后谈到。

在用户浏览完应用介绍页面之后,会调用JysAppTourActivity的这个函数:

	/**
	 * 启动注册登录页面,并关闭本页
	 * 【闫涛 2015.09.11】初始版本
	 */
	@Override
	protected void goRegisterLoginActivity() {
		JysRegisterLoginModel model = (JysRegisterLoginModel)WkyModel.getInstance(
				JysRegisterLoginModel.class.getCanonicalName() + WkyConstants.MODEL_OBJECT_DEFAULT,
				JysRegisterLoginModel.class);
		model.setObjectId(JysRegisterLoginModel.class.getCanonicalName() + WkyConstants.MODEL_OBJECT_DEFAULT);
		model.setState(JysRegisterLoginModel.STATE_REGISTER);
		Intent intent = new Intent(this, JysRegisterLoginActivity.class);
		startActivity(intent);
		finish();
	}

在这个函数中,会首先初始化一个JysRegisterLoginModel类的实例,方法为调用基类WkyModel.getInstance方法,当生成JysRegisterLoginModel类实例后,将标识设置为类的全名加default(在后面JysRegisterLoginActivity中会根据这个ID来获取本实例,同时会在onDestroy回调中,删除此ID的对象),将界面状态置为注册。

下面是JysRegisterLoginActivity类,由于该类中有很大一部分代码是用于实现界面的,这里就不重点介绍了。这里只重点介绍与MVC架构相关的内容。要理解本类,我们需要从其基类入手。

首先是WkyRegisterLoginModel.onCreate方法:

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		//setContentView(R.layout.activity_register_login);
		moveHeight = DensityUtil.dip2px(this, 50);
		inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
		model = getRegisterLoginModel();
		wkyRegisterLoginModel = (WkyRegisterLoginModel)model;
		thisActivity = this;
		int state = wkyRegisterLoginModel.getState();
	}

这里首先通过调用具体应用中的子类(JysRegisterLoginModel类)的getRegisterLoginModel方法,取出先前生成的模型类对象,并取出保存在其中的状态。

在具体应用中,如JysRegisterLoginModel.onCreate中,进行具体的初始化操作:

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(com.weikangyun.wkylib.R.layout.activity_register_login);
		getViewObjects();
		setupGuis();
		setupActionListeners();
	}	

	/**
	 * 生成并获取本Activity对应的模型类实例
	 * 【闫涛 2015.09.18】初始版本
	 */
	protected WkyModel getRegisterLoginModel() {
		return WkyModel.
				getInstance(JysRegisterLoginModel.class.getCanonicalName() + WkyConstants.MODEL_OBJECT_DEFAULT,
						JysRegisterLoginModel.class);
	}

上面代码首先设置布局文件,然后获取界面上View对象,然后根据模型类内容,初始化界面,最后是设置界面上事件响应函数。上述步骤与IOS中的基本相同,其中getViewObjects在IOS中是设置IBOutlets,而setupActionListeners对应IOS中的IBAction。

下面来看getViewObjects方法实现:

	/**
	 * 获取界面上所有View对象
	 * 【闫涛 2015.09.12】初始版本
	 */
	protected void getViewObjects() {
		contentView = (View)findViewById(R.id.content_view);
		rootView = (WkyKbRelativeLayout)findViewById(R.id.registerLoginRoot);
		scrollView = (ScrollView)findViewById(R.id.scrollview);
		loginNameEdtt = (WkyEditText)findViewById(R.id.login_name_edtt);
		loginPwdEdtt = (WkyEditText)findViewById(R.id.login_pwd_edtt);
		loginTempEdtt = (WkyEditText)findViewById(R.id.login_temp_edtt);
		forgetPwdTxtv = (TextView)findViewById(R.id.forget_pwd_txtv);
		userAgreementTxtv = (TextView)findViewById(R.id.user_agreement_txtv);
		switchStateTxtv = (TextView)findViewById(R.id.switch_state_txtv);
		clearLoginNameImgv = (ImageView)findViewById(R.id.clear_login_name_imgv);
		clearLoginPwdImgv = (ImageView)findViewById(R.id.clear_login_pwd_imgv);
		registerOrLoginImgv = (ImageView)findViewById(R.id.register_or_login_imgv);
		userAgreementLrlt = (LinearLayout)findViewById(R.id.user_agreement_lrlt);
		switchStateLabelTxtv = (TextView)findViewById(R.id.switch_state_label_txtv);
	}

实际上就是将页面上的View保存到对应的属性中。下一步是根据模型类中的数据,通过setupGuis方法来设置显示界面,代码如下所示:

	/**
	 * 根据状态设置界面元素是否显示
	 * 【闫涛 2015.09.12】初始版本
	 */
	protected void setupGuis() {
		switch (wkyRegisterLoginModel.getState()) {
		case WkyRegisterLoginModel.STATE_REGISTER:
			forgetPwdTxtv.setVisibility(View.GONE);
			userAgreementLrlt.setVisibility(View.VISIBLE);
			switchStateTxtv.setText("登录");
			switchStateLabelTxtv.setText("已有帐号?点击  ");
			registerOrLoginImgv.setImageResource(R.drawable.register);
			break;
		case WkyRegisterLoginModel.STATE_LOGIN:
			forgetPwdTxtv.setVisibility(View.VISIBLE);
			userAgreementLrlt.setVisibility(View.INVISIBLE);
			switchStateTxtv.setText("注册");
			switchStateLabelTxtv.setText("没有帐号?点击  ");
			registerOrLoginImgv.setImageResource(R.drawable.login);
			loginPwdEdtt.setHint("密码");
			forgetPwdTxtv.setText("忘记密码");
			break;
		case WkyRegisterLoginModel.STATE_FORGET_PWD:
			registerOrLoginImgv.setImageResource(R.drawable.reset_password);
			loginPwdEdtt.setHint("设置一个新密码,6-15位");
			forgetPwdTxtv.setText("返回登录");
			userAgreementLrlt.setVisibility(View.INVISIBLE);
			break;
		case WkyRegisterLoginModel.STATE_ACTIVATE:
			break;
		}
		clearLoginNameImgv.setVisibility(View.GONE);
		clearLoginPwdImgv.setVisibility(View.GONE);
	}

在本方法中,根据模型类JysRegisterLoginModel对象中保存的状态信息,显示相应的内容。这里一共有四种状态:注册、登录、忘记密码和激活。

接下来我们在setupActionListeners方法中,添加界面事件响应函数的定义:

	/**
	 * 设置界面上各个View的消息响应函数
	 * 【闫涛 2015.09.12】初始版本
	 */
	protected void setupActionListeners() {
		listenSoftKeyboardState();
		setUserAgreementLrltOnClickListener();
		setClearLoginNameImgvOnClickListener(); // 清空登录名内容
		setClearLoginPwdImgvOnClickListener(); // 清空密码
		setLoginNameEdttOnFocusChangeListener(); // 登录名失去获取焦点时显示或隐藏清除图标
		setLoginPwdEdttOnFocusChangeListener();  // 密码失去焦点时显示或隐藏右侧清除图标
		addLoginNameEdttTextChangedListener();
		addLoginPwdEdttTextChangedListener();
		setSwitchStateTxtvOnClickListener();
		setForgetPwdTxtvOnClickListener();
		setRegisterOrLoginImgvOnClickListener();
	}

分别作如下操作:

  1. 监听软键盘状态
  2. 用户点击用户协议的消息响应函数,利用WebView来显示用户协议
  3. 登录名清空图标的消息响应函数
  4. 登录密码清空图标的消息响应函数
  5. 登录名失去焦点的消息响应函数
  6. 登录密码失去焦点的消息响应函数
  7. 登录名内容改变消息响应函数
  8. 登录密码内容改变消息响应函数
  9. 状态切换(注册、登录、忘记密码、激活)消息响应函数
  10. 忘记密码点击的消息响应函数
  11. 注册或登录按钮消息响应函数

完成这些工作后,当用户点击注册时,就可以进入注册流程了。在下一节中,我们将首先讲一下Android平台下网络请求的实现方式,我们这里采用异步任务的方式来处理网络请求。

华丽的分隔线
******************************************************************************************************************************************************************************
希望大家多支持,有大家的支持,我才能走得更远,谢谢!
银行账号:622202 0200 1078 56128 闫涛
我的支付宝:[email protected]

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-11 13:50:40

最老程序员创业开发实训12---Android---在MVC架构下Activity设计及实现的相关文章

最老程序员创业开发实训4---IOS平台下MVC架构

在前面几篇文章中,我们大致研究了一下,在Android平台,以应用开始时的Splash页面为例,讲述了怎样利用MVC架构来实现这一简单功能,有可能有朋友认为,对于这样简单的功能,采用MVC架构有些过了.但是,如果需求变为,需要根据时间.地点等,显示从服务器上下载的图片,那么我们所采用的架构,就具有一定的优势了. 下面,我们将讲述在IOS平台怎样实现相同的功能.我们知道在IOS平台上开发原生应用,有两种技术可供选择,即Objective-C或Swift.如果对于找工作而言,当前最好的选择依然是Ob

最老程序员创业开发实训14---PHP---用户体系数据库设计

在做完了之前的一系列工作之后,终于要进行应用后台的设计和实现环节了.在后台设计中,我们觉得数据库的设计是最重要的根基,因为所有业务逻辑均是架构在数据库的基础之止,如果对数据库进行修改,程序可能需要大改,工作量将非常之大,所以数据库设计必须非常重视. 在谈数据库设计之前,我们先谈一下ORM,即关系数据库与面向对象系统的映射,其理由是面向对象开发人员,不了解关系型数据库,因些引入ORM,使其不需要学习关系型数据库就可以进行数据库开发.我们认为,关系型数据已经有了几十年的发展历史,理论和实践都很成熟,

最老程序员创业开发实训8---IOS---在Swift中用定时任务显示Splash页面

在上一节中,我们用Swift实现了Splash页面的显示,但是仅仅显示Splash页面是不够的,我们需要显示Splash页面2秒,然后跳转到下一个页面,因此需要实现定时任务的功能.在Android中,我们采用了系统的函数postDelayed来实现这一功能,在IOS系统中,我们需要使用GCD. 首先我们简单了解一下GCD.我们知道,对于手机而言,多核CPU用得越来越多,这样真正的多任务就是益成为现实,因为每个CPU核都可以独立地执行单独的任务.GCD正是为了使程序员更方便地使用多核CPU而引入的

最老程序员创业开发实训2---采用MVC架构的应用Splash页面实现

在基本所有的应用中,一点应用图标,都会弹出一个Splash页面,显示几秒钟,然后再进入到程序的主页面中(如果是用户第一次使用,会进入一个新手引导系列页面,介绍产品的主要功能).今天我们就来开发这个页面. 这个页面是几乎所有应用都会用到的页面,所以我们希望在多个应用中重用,怎么来实现呢?在Android中,我们可以将这个页面做成一个工程项目,所有其他应用项目,都引用这个工程项目,就可以直接使用这个Splash页面的实现了. 我们先建立一个普通的Android工程(我们在调通这个功能之后,我们会将其

最老程序员创业开发实训3---采用MVC架构的应用Splash页面实现

在上篇文章中,我们已经将Splash页面显示封装到了WkyLib工程中,在本节中,我们将建立一个具体应用工程:维康基因基因师版(WkgJys),是一款面向基因师的工具软件,可以使基因师更好的管理客户,建立自己的个人品牌,向客户提供在线咨询.线下预约咨询等功能.这只是一款假想中的软件,我们不用太去考虑软件的商业价值,我们的重点是如体来实现这款软件. 建立WkgJys工程,首先我们设定这个工程需要依赖于我们上节所建立的库工程WkyLib,方法是选中WkgJys项目,按右键,选择项目属性=>Andro

最老程序员创业开发实训13---Android---网络请求与异步任务

在完成了用户注册和登录页面的界面设计工作之后,我们就需要让我们的程序向后台发起请求,请求后台PHP程序实际进行用户注册操作.在新版本的Android系统中,所有的网络请求必须以异步的方式来进行,我们既可以通过线程方式也可以通过Android系统为我们提供的异步任务方式来完成,我们在这里选择采用异步任务的方式来进行网络操作. 根据异步任务的原理,当应用调用异步任务时,异步任务会在后台完成相应的网络操作,在完成之后,在onPostExecute方法中通知界面,更新操作状态.有两种方法可以完成这项任务

最老程序员创业开发实训7---Cocoa Touch Framework实现Splash屏幕功能

在Xcode中建立好工程空间(Work Space)之后,并且建立Cocoa Touch Framework工程WkyLib和应用工程WkgJys工程,下面我们就可以开始进行正式开发了. 首先我们进入Cocoa Touch Framework工程WkyLib,先在下面创建如下组用于组织代码:common, model, view, controller,如下图所示: 同时,在WkyLib的目录下,创建相同的目录common, model, view, controller, images: 在v

最老程序员创业开发实训6---用Swift创建Framework工程重用代码

由于我们要开发一系列应用,很多基础功能是通用的,我们希望这些通用功能可以实现不同程序之间重用,在IOS开发中,可以通过静态库和Framework两种方式来实现,我们选择采用Framework方式,因为这种方式更加灵活.在本节中,我们将创建一个CocoaTouch Framework工程WkyLib,实现Splash屏幕功能,然后创建WkgJys应用,调用WkyLib中的Splash屏幕功能. 新建一个在文件=>新建中选择新建Workspace,如下图所示: 在Xcode中建立Cocoa Touc

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

用户在观看完应用介绍页面之后,会点击进入应用按钮,这时由于用户是第一次运行,所以会弹出注册页面.如果是老用户,启动应用时,在Splash页面之后,如果应用记录着用户的登录信息,测直接进入主页面,如果从本地取不到用户登录信息,则将显示登录页面. 注册和登录功能看起来很简单,但是由于我们这里需要实现一个完整的应用支撑基础设施,因此需要分几个部分来进行.我们首先会讨论怎样创建并使用Activity中会用到的Model类,在这中间我们会采用Application对象作为中心信息仓库,每个Model类只是