当前位置: 代码迷 >> Android >> 最老软件工程师创业开发实训13-Android-网络请求与异步任务
  详细解决方案

最老软件工程师创业开发实训13-Android-网络请求与异步任务

热度:87   发布时间:2016-04-27 22:02:51.0
最老程序员创业开发实训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]








1楼traburiss3小时前
异步任务的onpostexecute本来就是在UI线程里面运行的,再去用handler其实多次一举,反而和异步任务本来的设计目的背道而驰。n如果想要松耦合,那还是老老实实的Thread加handler。
  相关解决方案