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

在完成了用户注册和登录页面的界面设计工作之后,我们就需要让我们的程序向后台发起请求,请求后台PHP程序实际进行用户注册操作。在新版本的Android系统中,所有的网络请求必须以异步的方式来进行,我们既可以通过线程方式也可以通过Android系统为我们提供的异步任务方式来完成,我们在这里选择采用异步任务的方式来进行网络操作。

根据异步任务的原理,当应用调用异步任务时,异步任务会在后台完成相应的网络操作,在完成之后,在onPostExecute方法中通知界面,更新操作状态。有两种方法可以完成这项任务,一种是将Activity对象放到异步任务类中,当需要更新界面时,直接调用该Activity对象的方法即可,另一种方式是传入Activity对象的Handler对象,当异步任务完成网络操作时,向Handler对象发送消息,由Handler对象来更新界面。从上面的分析可以看出,第一种方法使Activity和异步任务之间产生了紧耦合,是软件开发中不太提倡的,因此我们采用第二种方式,即采用Handler对象,异步任务通过发送消息通知Activity更新界面状态。

我们首先在JysRegisterLoginActivity类中,定义与异步任务交互的Handler:

	static protected class JysRegisterLoginHandler extends WkyRegisterLoginHandler {
		public JysRegisterLoginHandler(JysRegisterLoginActivity activity) {
			this.activity = activity;
		}

		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			// 自己额外的处理
			switch (msg.what) {
			case WkyConstants.MSG_REGISTER_USER:
				activity.processRegisterUserResult(msg);
				break;
			}
		}
		private JysRegisterLoginActivity activity = null;
	}

需要注意的是,我们将JysRegisterLoginHandler声明为静态的内部类,因为如果只声明为内部类,有出现内存泄露的可能性。
在Activity的onCreate函数中,初始化这个Hanlder对象。

handler = new JysRegisterLoginHandler(this);

我们在用户点击注册按钮时,调用异步任务发起网络请求,请求PHP程序完成用户注册功能。

	/**
	 * 点击注册/登录按钮
	 * 【闫涛 2015.09.16】初始版本
	 */
	protected void setRegisterOrLoginImgvOnClickListener() {
		registerOrLoginImgv.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				Log.e("wky", "register or login to the system...");
				if (wkyRegisterLoginModel.getState() == WkyRegisterLoginModel.STATE_REGISTER) {
					registerUser();
				} else if (wkyRegisterLoginModel.getState() == WkyRegisterLoginModel.STATE_LOGIN) {
					Log.e("wky", "login the user");
				}
			}
		});
	}

	protected void registerUser() {
		Log.e("wky", "Regisger the user");
		if (null == registerTask) {
			registerTask = new WkyRegisterAsyncTask(this, handler);
			String urlStr = WkyConstants.CMD_REGISTER_USER;
			Log.e("wky", "url=" + urlStr + "!");
			String body = prepareRegisterReqBody();
			registerTask.execute(urlStr, body);
		}
	}

异步任务需要两个参数,一个是请求URL,另一个是Json格式的请求数据。
在这里顺便提一下编程规范的问题,大家看请求的URL是定义在WkyConstants里的一个常量,而不是直接写字符串,这样便于日后的代码维护。我们在代码中要尽量避免在代码中直接写数字和字符串,因为我们在维护时可能会忘记数字的含义,字符串容易在不同的地方写得不一致,造成比较难于调试的BUG。
下面是具体的异步任务类:

	/**
	 * 异步任务开始前的回调函数
	 * 【闫涛 2015.09.24】初始版本
	 */
	@Override
	protected void onPreExecute() {
		Log.e("wky", "WkyRegisterAsyncTask.onPreExecute 1");
	}

	/**
	 * 具体异步任务执行函数
	 * 【闫涛 2015.09.24】初始版本
	 */
	@Override
	protected String doInBackground(String... params) {
		String urlStr = params[0];
		String body = params[1];
		return WkyHttpClient.doPost(urlStr, body);
	}

	/**
	 * 更新异步任务状态信息(在显示进度条时会用到)
	 * 【闫涛 2015.09.24】初始版本
	 */
	@Override
	protected void onProgressUpdate(Integer... progress) {
	}

	/**
	 * 异步任务结束时要调用的方法,通知页面进行更新
	 * 【闫涛 2015.09.24】初始版本
	 */
	@Override
	protected void onPostExecute(String result) {
		Log.e("wky", "new:" + result);
		Message msg = handler.obtainMessage();
		msg.what = WkyConstants.MSG_REGISTER_USER;
		Bundle params = new Bundle();
		params.putString(WkyConstants.MSG_DATA_NAME, result);
		msg.setData(params);
		handler.dispatchMessage(msg);
	}

从上面的代码中可以看出,在doInBackground中调用网络POST请求方法,发送POST请求。这里重点是在onPostExecute方法中,生成一个Message对象,将POST响应字符串,添加到Message对象中,然后向Handler对象发送消息。在前面Handler类的代码中,接收到这个消息,就会调用相相应的方法来处理响应结果了。代码如下所示:

	public void processRegisterUserResult(Message msg) {
		String jsonStr = msg.getData().getString(WkyConstants.MSG_DATA_NAME);
		JSONObject json = null;
		String status = null;
		long userId = 0;
		try {
			json = new JSONObject(jsonStr);
			status = json.getString("status");
			userId = json.getLong("userId");
			Log.e("wky", "^_^ registerUser:" + status + "; u=" + userId + "!");
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

在这里我们什么也没做,只是把响应结果变为json对象,从中取出status和userId等项目,在实际的代码中,我们需要记录下用户的信息,然后转到应用首页中去。
下面是具体发起网络请求的类:

	/**
	 * 普通POST请求,窗体形式,没有文件上传操作
	 * @param urlStr
	 * @param data 以JSON格式存在
	 * @return 响应字符串
	 * 【闫涛 2015.09.23】初始版本
	 */
	public static String doPost(String urlStr, String data) {
		HttpURLConnection conn = null;
		OutputStreamWriter outStream = null;
		StringBuilder result = new StringBuilder();
		try {
			URL url = new URL(urlStr);
			conn = (HttpURLConnection) url.openConnection();
			conn.setDoOutput(true);
			conn.setDoInput(true);
			conn.setRequestProperty("charset", "utf-8");
			conn.setRequestMethod(POST);
			conn.setRequestProperty("Content-type",
					"application/x-www-form-urlencoded");
			conn.setConnectTimeout(TIMEOUT);
			conn.setReadTimeout(TIMEOUT);
			conn.connect();
			outStream = new OutputStreamWriter(conn.getOutputStream(), "UTF-8");
			if (data != null) {
				outStream.write(data);
			}
			outStream.flush();
			outStream.close();
			// }

			if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
				result.append(readAsString(conn.getInputStream(), "UTF-8"));
			}else{
				Log.e("wky","ResponseCode:" + conn.getResponseCode());
			}

		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return result.toString();

	}

由于我们的网络请求处理比较简单,因此直接采用了Java的方法来进行网络请求。

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

时间: 2024-10-22 18:59:20

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

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

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

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

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

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

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

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

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

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

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

最老程序员创业开发实训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

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

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

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

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