最老程序员创业开发实训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 闫涛
我的支付宝:yt7589@hotmail.com








  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值